Monday, 17 December 2012

Making WPF DataGrid Keyboard friendly

The out of the box DataGrid does a great job of making available data, but the standard default config leaves a little to be desired to those stuck with a keyboard.

I aim to show you how to make it a little friendlier with the help of a custom behavior.

First we create a custom binding.
   public class DataGridListBehavior : Behavior<DataGrid>  
   {  
     private bool _endingEdit;  
     protected IList Model { get; private set; }  
     protected override void OnAttached()  
     {  
       AssociatedObject.DataContextChanged += HandleDataContextChanged;  
       AssociatedObject.MouseDoubleClick += HandleMouseDoubleClick;  
       AssociatedObject.CellEditEnding += HandleCellEditEnding;  
       AssociatedObject.PreviewKeyDown += PreviewKeyDown;  
       AssociatedObject.PreviewMouseLeftButtonDown += HandleLeftButtonDown;  
       AssociatedObject.GotFocus += CellGotFocus;  
     }  
     protected override void OnDetaching()  
     {  
       ....  

This allows up to hook important grid events and add in our custom code.

Most of the work is done by CellGotFocus().

     private void CellGotFocus(object sender, RoutedEventArgs args)  
     {  
       DataGridCell gridCell = args.OriginalSource as DataGridCell;  
       if (gridCell != null)  
       {  
         DataGridHelper.EnterEdit(gridCell, AssociatedObject);  
       }  
     }  

Inside here we do the major work of ensuring we enter into the cell then focus the control automatically.

     public static void EnterEdit(DataGridCell gridCell, DataGrid grid, bool bFocus = true)  
     {  
       if (gridCell != null && !gridCell.IsEditing)  
       {  
         // enables editing on single click  
         if (!gridCell.IsFocused)  
           gridCell.Focus();  
         if (!gridCell.IsSelected && grid.SelectionUnit == DataGridSelectionUnit.Cell)  
           gridCell.IsSelected = true;  
         grid.BeginEdit();  
         if (bFocus)  
         {  
           var control = FindChildElement<Control>(gridCell);  
           if (control != null)  
           {  
             control.Focus();  
           }  
         }  
       }  
     }  

You can get the code here.

No comments:

Post a Comment