Home Forums WPF controls Xceed DataGrid for WPF Keydown event

Viewing 15 posts - 1 through 15 (of 18 total)
  • Author
    Posts
  • User (Old forums)
    Member
    Post count: 23064
    #22737 |

    I use a DataGridControl with the following set:

    myDataGridControl.SelectionMode = SelectionMode.Single
    myDataGridControl.ReadOnly = True
    myDataGridControl.CellEditorDisplayConditions = CellEditorDisplayConditions.None
    myDataGridControl.NavigationBehavior = NavigationBehavior.RowOnly

    I wrote a small Keydown handler:

    Private Sub myDataGridControl_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Input.KeyEventArgs) Handles myDataGridControl.KeyDown
    Select Case e.Key
    Case Key.Down
    MsgBox(“Down!”)
    Case Key.Up
    MsgBox(“Up!”)
    Case Key.Enter
    MsgBox(“Enter!”)
    Case Key.Delete
    MsgBox(“Delete!”)
    Case Key.Space
    MsgBox(“Space!”)
    End Select
    End Sub

    After binding a dataset to myDataGridControl only pressing space fires the event. I can use the up and down keys but the event does not fire. What would be a better way to handle the KeyDown event at the datarow level?

    Imported from legacy forums. Posted by Emmanuel (had 12008 views)

    User (Old forums)
    Member
    Post count: 23064

    By the way I do use this method:

    EventManager.RegisterClassHandler(GetType(DataRow), DataRow.MouseLeftButtonDownEvent, New MouseButtonEventHandler(AddressOf OnDataRowMouseClick))

    EventManager.RegisterClassHandler(GetType(DataRow), DataRow.MouseDoubleClickEvent, New MouseButtonEventHandler(AddressOf OnDataRowMouseDoubleClick))

    For the mouse events and that works great. I just couldn’t find a way to do the same for keyboard events.

    Imported from legacy forums. Posted by Emmanuel (had 315 views)

    User (Old forums)
    Member
    Post count: 23064

    I have a similar problem with KeyDown event on the GridControl
    I used the PreviewKeyDown event instead and that fires fine.

    this.PreviewKeyDown += new KeyEventHandler(CustomDataGridControl_PreviewKeyDown);

    I know that not the WPF way to register events but It still works and I dont need a routed event.

    Imported from legacy forums. Posted by MiddleTommy (had 596 views)

    User (Old forums)
    Member
    Post count: 23064

    wait that is C# dont know if it is the same in VB

    Imported from legacy forums. Posted by MiddleTommy (had 722 views)

    User (Old forums)
    Member
    Post count: 23064

    Handles myDataGridControl.PreviewKeyDown

    Imported from legacy forums. Posted by MiddleTommy (had 874 views)

    User (Old forums)
    Member
    Post count: 23064

    MiddleTommy, thanks for the tip, I’ll try it out.

    Thanks for the translation to VB, but don’t worry about such C#/VB.NET differences in the future. I think we all run into sample code that’s either in C# or VB.NET and doesn’t match our prefered language – we naturally become polyglots. 🙂

    Imported from legacy forums. Posted by Emmanuel (had 567 views)

    User (Old forums)
    Member
    Post count: 23064

    Using the PreviewKeyDown event I am able to handle Key.Down, Key.Up, etc… But I’m having another problem: I get wrong information on the datarow. Here’s my code:

    Private Sub myDataGridControl_PreviewKeyDown(ByVal sender As Object, ByVal e As System.Windows.Input.KeyEventArgs) Handles myDataGridControl.PreviewKeyDown
    Select Case e.Key
    Case Key.Down, Key.Up
    Dim oDataRow As DataRow = myDataGridControl.ItemContainerGenerator.ContainerFromItem(myDataGridControl.SelectedItem)
    Call MyChildPanelUpdate(oDataRow)
    e.Handled = False
    End Select
    End Sub

    The problem is that myDataGridControl.ItemContainerGenerator.ContainerFromItem(myDataGridControl.SelectedItem) is the wrong datarow – it’s basically the previous row that I was on before clicking on the Up or Down keys.

    Has someone successfully used code code similar to the one that works for mouse events? Something like this:

    EventManager.RegisterClassHandler(GetType(DataRow), DataRow.MouseDoubleClickEvent, New MouseButtonEventHandler(AddressOf OnDataRowMouseDoubleClick))

    This way when I define the delegate:

    Private Sub OnDataRowMouseDoubleClick(ByVal sender As Object, ByVal e As MouseButtonEventArgs)

    The sender is basically my datarow, so I can just go:

    Dim oDataRow As DataRow = sender

    I tried doing this:

    EventManager.RegisterClassHandler(GetType(DataRow), DataRow.PreviewKeyDownEvent, New KeyboardEventHandler(AddressOf OnDataRowPreviewKeyDownEvent))

    And then:

    Private Sub OnDataRowPreviewKeyDownEvent(ByVal sender As Object, ByVal e As System.Windows.Input.KeyboardEventArgs)
    Dim oDataRow As DataRow = sender
    If Not (oDataRow Is Nothing) Then
    If e.KeyboardDevice.IsKeyDown(Key.Down) Or e.KeyboardDevice.IsKeyDown(Key.Up) Then Call MyChildPanelUpdateFunction(oDataRow)
    If e.KeyboardDevice.IsKeyDown(Key.Enter) Or e.KeyboardDevice.IsKeyDown(Key.Space) Then Call MyOpenNewWindowFunction(oDataRow)
    End If
    e.Handled = False
    End Sub

    But I get an exception on RegisterClassHandler:

    “Handler type is mismatched.”

    How can I catch the key.down or key.up events and figure out which datarow is now selected?

    Imported from legacy forums. Posted by Emmanuel (had 795 views)

    Xceed Support
    Member
    Post count: 5658

    Just to be sure: Do you have a strong desire to catch the Key.Up and Key.Down events? \

    Because there might be alternate ways to detect that user selection changed without the need to trap these events (typically, Preview*** events will occur before any code is executed to change the Current or Selected item).

    Namely, you could register to the SelectedItem’s change notification and then you can get the DataRow for the item. (this can be done through DependencyPropertyDescriptor.AddValueChanged() ).

    Concerning the “Handler type is mismatched.” error. Its because for the PreviewKeyDown event, the handler should be of type KeyEventHandler (not KeyboardEventHandler).

    Imported from legacy forums. Posted by Marcus [Xceed] (had 726 views)

    User (Old forums)
    Member
    Post count: 23064

    use CurrentItem instead of SelectedItem

    Imported from legacy forums. Posted by MiddleTommy (had 716 views)

    User (Old forums)
    Member
    Post count: 23064

    Hi Marcus,

    You are right on the page: I would much prefer to detect that user selection changed. This way I don’t have to worry about whether the change occured because of a mouse click or a keyboard Key.Up or Key.Down event.

    Can you point me to an example I could look at that uses DependencyPropertyDescriptor.AddValueChanged() ?

    Thanks.

    Imported from legacy forums. Posted by Emmanuel (had 720 views)

    Xceed Support
    Member
    Post count: 5658

    Sorry, I have no code samples or examples of using this… but it’s pretty straightforward:

    <code>
    DependencyPropertyDescriptor myDescriptor = DependencyPropertyDescriptor.FromProperty( DataGridControl.SelectedItemProperty, typeof(DataGridControl));

    myDescriptor.AddValueChanged( myDataGridInstance, new EventHandler( MyHandlingFunction) );
    </code>

    From the point where you set this, you will receive notification of changes to the SelectedItem property of the DataGridControl’s instance in the MyHandlingFunction.

    Imported from legacy forums. Posted by Marcus [Xceed] (had 645 views)

    User (Old forums)
    Member
    Post count: 23064

    <code>
    public class CustomDataGridControl : DataGridControl
    {
    private const string SELECTEDITEM = “SelectedItem”;
    private const string CURRENTITEM = “CurrentItem”;
    public event ItemChangedHandler SelectedItemChanged;
    private bool arrowDown;
    private Timer arrowTimer;

    public bool ArrowDown
    {
    get { return arrowDown; }
    }

    public CustomDataGridControl():base()
    {
    this.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(CustomDataGridControl_PropertyChanged);
    arrowDown = false;
    this.PreviewKeyDown += new KeyEventHandler(CustomDataGridControl_PreviewKeyDown);
    this.KeyUp += new KeyEventHandler(CustomDataGridControl_KeyUp);
    try
    {
    arrowTimer = new Timer(400);
    arrowTimer.AutoReset = true;
    arrowTimer.Elapsed += new ElapsedEventHandler(arrowTimer_Elapsed);
    }
    catch(System.Exception ex){QuestionBox.Ask(ex.ToString());}
    }

    void arrowTimer_Elapsed(object sender, ElapsedEventArgs e)
    {
    arrowTimer.Stop();
    this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new VoidHandler(OnCurrentItemChanged));
    }

    private void OnCurrentItemChanged()
    {
    if(this.SelectedItemChanged!=null)
    this.SelectedItemChanged(this.CurrentItem);
    }

    private void OnSelectedItemsChanged()
    {
    if (this.SelectedItemChanged != null)
    this.SelectedItemChanged(this.CurrentItem);
    }

    void CustomDataGridControl_PreviewKeyDown(object sender, KeyEventArgs e)
    {
    if (e.Key == Key.Down || e.Key == Key.Up)
    arrowDown = true;

    }

    void CustomDataGridControl_KeyUp(object sender, KeyEventArgs e)
    {
    if (e.Key == Key.Up || e.Key == Key.Down)
    {
    arrowDown = false;
    arrowTimer.Stop();
    arrowTimer.Start();
    }
    }

    void CustomDataGridControl_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
    if (e.PropertyName == SELECTEDITEM || e.PropertyName == CURRENTITEM)
    if (!arrowDown)
    {
    arrowTimer.Stop();
    //arrowTimer.Interval = 10;
    arrowTimer.Start();
    //arrowTimer.Interval = 300;
    }

    }

    public Window Owner
    {
    get
    {
    return FindWindowParent(this);

    }
    }

    private Window FindWindowParent(FrameworkElement ctl)
    {
    if (ctl.Parent is Window)
    return (Window)ctl.Parent;
    else if (ctl.Parent == null)
    return null;
    return FindWindowParent((FrameworkElement)ctl.Parent);

    }
    protected override DependencyObject GetContainerForItemOverride()
    {
    return new CustomDataRow();

    }
    }
    </code>

    Imported from legacy forums. Posted by MiddleTommy (had 2910 views)

    User (Old forums)
    Member
    Post count: 23064

    The timer and arrow down events are for delaying the fire of SelectedItemChanged.

    So when the user presses the UP/DOWN arrow to select a row; if he presses it again before the timer elapses the event is not fired causing slow performance every time the row changes.

    The timer also works with mouse clicks because it was a quick fix to prevent the the event from going off before the row was visually selected.

    I have 3 grids and when the user selects a row in one grid it changes the data in another grid which is just setting a filter on a dataview. But there was slow performance when scrolling up rows with the arrow keys so I created the arrow/timer functionality as a work around.

    Imported from legacy forums. Posted by MiddleTommy (had 1885 views)

    User (Old forums)
    Member
    Post count: 23064

    forgot this line;

    public delegate void VoidHandler();

    Imported from legacy forums. Posted by MiddleTommy (had 732 views)

    User (Old forums)
    Member
    Post count: 23064

    forgive my code it was just a copy and paste
    I am finding some duplicate code.
    There is something about posting code on a forum.
    You find more mistakes.(atleast I do)

    Imported from legacy forums. Posted by MiddleTommy (had 469 views)

Viewing 15 posts - 1 through 15 (of 18 total)
  • You must be logged in to reply to this topic.