gpt4 book ai didi

WPF DataGrid - 创建一个新的自定义列

转载 作者:行者123 更新时间:2023-12-04 08:26:25 30 4
gpt4 key购买 nike

我正在尝试创建自己的复选框列(替换默认的),以便稍后移动到更复杂的数据列,我有以下代码:

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() .
    有谁知道这里出了什么问题?

    编辑:

    看来,如果我返回一个 TextBlock从内部 GenerateElement()它使其他方法被调用(尽管通知问题没有得到解决)。但是为什么这不适用于 CheckBoxes?默认复选框列如何工作???

    最佳答案

    好的。这是自定义 CheckBox 列的完整代码。看来,为了在 DataGrid 中将复选框之类的控件作为显示(而非编辑)元素,您必须使其 HitTest 不可见。或者您可以简单地使用 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;
    }
    }
    //--------------------------------------------------------------------------------------------

    关于WPF DataGrid - 创建一个新的自定义列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17381753/

    30 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com