创建一个新的自定义列
我尝试创建自己的复选框列(替换默认值),以便稍后移动到更复杂的数据列,并且我有以下代码:
public class MyCheckBoxColumn : DataGridBoundColumn
{
protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
{
var cb = new CheckBox();
var bb = this.Binding as Binding;
var b = new Binding { Path = bb.Path, Source = cell.DataContext };
cb.SetBinding(ToggleButton.IsCheckedProperty, b);
return cb;
}
protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
{
var cb = new CheckBox();
var bb = this.Binding as Binding;
var b = new Binding { Path = bb.Path, Source = ToggleButton.IsCheckedProperty };
cb.SetBinding(ToggleButton.IsCheckedProperty, b);
return cb;
}
protected override object PrepareCellForEdit(FrameworkElement editingElement, RoutedEventArgs editingEventArgs)
{
var cb = editingElement as CheckBox;
return cb.IsChecked;
}
protected override void CancelCellEdit(FrameworkElement editingElement, object uneditedValue)
{
var cb = editingElement as CheckBox;
if (cb != null) cb.IsChecked = (bool)uneditedValue;
}
protected override bool CommitCellEdit(FrameworkElement editingElement)
{
var cb = editingElement as CheckBox;
BindingExpression binding = editingElement.GetBindingExpression(ToggleButton.IsCheckedProperty);
if (binding != null) binding.UpdateSource();
return true;// base.CommitCellEdit(editingElement);
}
}
我的自定义DataGrid:
public class MyDataGrid : DataGrid
{
protected override void OnAutoGeneratingColumn(DataGridAutoGeneratingColumnEventArgs e)
{
try
{
var type = e.PropertyType;
if (type == typeof(bool))
{
var col = new MyCheckBoxColumn();
col.Binding = new Binding(e.PropertyName) {Mode = BindingMode.TwoWay};
e.Column = col;
}
else
{
base.OnAutoGeneratingColumn(e);
}
var propDescr = e.PropertyDescriptor as System.ComponentModel.PropertyDescriptor;
e.Column.Header = propDescr.Description;
}
catch (Exception ex)
{
Utils.ReportException(ex);
}
}
}
现在,除了两件事情之外,一切似乎都很好:
MyCheckBoxColumn
唯一使用的方法是GenerateElement()
。 所有其他方法都没有使用。 我已经在它们中加入了断点,并且它们从未被击中...... ObservableCollection
作为数据源,而其余列在通知我时会通知我,但这不是。 奇怪的是,当您检查/取消选中复选框时, bool
值会发生变化,但没有通知,也不会通过CommitCellEdit()
。 有人知道这里出了什么问题吗?
编辑:
看起来,如果我从GenerateElement()
返回一个TextBlock
,它会调用其他方法(但通知问题不会被修复)。 但为什么这不与CheckBoxes一起使用? 默认复选框列如何工作?
好。 以下是自定义CheckBox列的完整代码。 看起来,为了让一个控件像复选框一样在DataGrid中显示(而不是编辑)元素,你必须使它不可见。 或者您可以简单地使用TextBlock来显示一些类似于复选标记的字符:
public class MyCheckBoxColumn : DataGridBoundColumn
{
protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
{
var cb = new CheckBox() { IsHitTestVisible = false, HorizontalAlignment = HorizontalAlignment.Center, HorizontalContentAlignment = HorizontalAlignment.Center };
var bb = this.Binding as Binding;
var b = new Binding { Path = bb.Path, Source = dataItem, Mode = BindingMode.TwoWay };
cb.SetBinding(ToggleButton.IsCheckedProperty, b);
return cb;
// var cb = new TextBlock() { TextAlignment = TextAlignment.Center, HorizontalAlignment = HorizontalAlignment.Center };
// var bb = this.Binding as Binding;
// var b = new Binding { Path = bb.Path, Source = dataItem, Mode = BindingMode.TwoWay, Converter = new MyBoolToMarkConverter() };
// cb.SetBinding(TextBlock.TextProperty, b);
// return cb;
}
protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
{
var cb = new CheckBox() { HorizontalAlignment = HorizontalAlignment.Center, HorizontalContentAlignment = HorizontalAlignment.Center };
var bb = this.Binding as Binding;
var b = new Binding { Path = bb.Path, Source = dataItem, Mode = BindingMode.TwoWay };
cb.SetBinding(ToggleButton.IsCheckedProperty, b);
return cb;
}
protected override object PrepareCellForEdit(FrameworkElement editingElement, RoutedEventArgs editingEventArgs)
{
var cb = editingElement as CheckBox;
if (cb != null) return cb.IsChecked;
return false;
}
protected override void CancelCellEdit(FrameworkElement editingElement, object uneditedValue)
{
var cb = editingElement as CheckBox;
if (cb != null) cb.IsChecked = (bool)uneditedValue;
}
protected override bool CommitCellEdit(FrameworkElement editingElement)
{
// The following 2 lines seem to help when sometimes the commit doesn't happen (for unknown to me reasons).
//var cb = editingElement as CheckBox;
//cb.IsChecked = cb.IsChecked;
BindingExpression binding = editingElement.GetBindingExpression(ToggleButton.IsCheckedProperty);
if (binding != null) binding.UpdateSource();
return true;// base.CommitCellEdit(editingElement);
}
}
//--------------------------------------------------------------------------------------------
public class MyBoolToMarkConverter : IValueConverter
{
const string cTick = "■";
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value.GetType() != typeof(bool)) return "";
bool val = (bool)value;
return val ? cTick : "";
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value.GetType() != typeof(string)) return false;
string val = (string)value;
return val == cTick;
}
}
//--------------------------------------------------------------------------------------------
链接地址: http://www.djcxy.com/p/72475.html