开发者

Delete cell content in a WPF DataGrid when the Delete Key is pressed

Any idea on how I can achieve the following in a .Net 4 DataGrid:

private void grid_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Delete)
    {
        DataGridCell cell = e.OriginalSource as DataGridCell;

        if (cell == null) { return; }

        if (!cell.IsReadOnly && cell.IsEnabled)
        {
            // Set the cell content (and the property of the object binded to it)
            // to null
        }
    }
}

This behavior should work with any cell, so I don't want to hardcode column or property names.

EDIT: Solution I came up with:

if (e.Key == Key.Delete)
{
    DataGridCell cell = e.OriginalSource as DataGridCell;

     if (cell == n开发者_如何学编程ull) { return; }

     if (!cell.IsReadOnly && cell.IsEnabled)
     {
          TextBlock tb = cell.Content as TextBlock;

          if (tb != null)
          {
               Binding binding = BindingOperations.GetBinding(tb, TextBlock.TextProperty);

               if (binding == null) { return; }

               BindingExpression exp = BindingOperations.GetBindingExpression(tb, TextBlock.TextProperty);

               PropertyInfo info = exp.DataItem.GetType().GetProperty(binding.Path.Path);

               if (info == null) { return; }

               info.SetValue(exp.DataItem, null, null);
          }
    }
}


There a couple of things I had to do to get this to work:

  1. Filter out delete key presses when editing (couldn't find an obvious way to detect if in editing mode):

    private bool _isEditing = false;
    private void datagrid_BeginningEdit(object sender, DataGridBeginningEditEventArgs e)
    {   _isEditing = true; }
    
    private void datagrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
    {   _isEditing = false; }
    
  2. Handle the KeyUp message (KeyDown message was handled by datagrid):

    private void dataGrid_KeyUp(object sender, KeyEventArgs e)
    {
        if (!_isEditing && e.Key == Key.Delete && Keyboard.Modifiers == ModifierKeys.None)
        {
            foreach (var cellInfo in dataGrid.SelectedCells)
            {
               var column = cellInfo.Column as DataGridBoundColumn;
               if (column != null)
               {
                  var binding = column.Binding as Binding;
                  if (binding != null)
                      BindingHelper.SetSource(cellInfo.Item, binding, null);
               }
            }
        }
    }
    
  3. Use a framework helper class to route the value = null to the underlying view model

    public class BindingHelper: FrameworkElement
    {
       public static void SetSource(object source, Binding binding, object value)
       {
           var fe = new BindingHelper();
           var newBinding = new Binding(binding.Path.Path)
           {
               Mode = BindingMode.OneWayToSource,
               Source = source,
           };
           fe.SetBinding(ValueProperty, newBinding);
           fe.Value = value;
        }
    
        #region Value Dependency Property
        public object Value
        {
            get { return (object)GetValue(ValueProperty); }
            set { SetValue(ValueProperty, value); }
        }
    
        public static readonly DependencyProperty ValueProperty =
           DependencyProperty.Register("Value", typeof(object), typeof(BindingHelper));
        #endregion
    }
    


That could be pretty complicated, depending on the template of the cell, etc.

I'd imagine you'd have to use various BindingOperations methods (BindingOperations.GetBinding, BindingOperations.GetBindingExpression, etc) to mess with the bound value?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜