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:
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; }
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); } } } }
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?
精彩评论