【问题标题】:How to set custom column's datacontext to ItemsSource item type?如何将自定义列的数据上下文设置为 ItemsSource 项目类型?
【发布时间】:2020-12-29 20:22:47
【问题描述】:

我试图了解框架的默认实现如何设法拥有 itemssource 项的数据上下文。具体来说,当设置了 DataGrid 的 ItemsSource(例如设置为 Foo 对象的集合)并且您在 DataGrid.Columns 属性中定义列时,DataGridTextColumn “Binding”属性需要来自 Foo 对象的属性。

以下代码可能更好地说明问题:

public class MainWindowViewModel
{
    public List<Foo> Foos { get; }
}

public class Foo
{
    public string FooDesignation { get; }
}

我非常简单的视图模型包含我的 DataGrid 的集合。然后我希望使用我自己的自定义列添加到 DataGrid 的列集合中:

public class CustomDataGridTextColumn : DataGridTextColumn
{
    public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
        nameof(Text), 
        typeof(string), 
        typeof(CustomDataGridTextColumn), 
        new PropertyMetadata(default(string)));

    public string Text
    {
        get => (string) this.GetValue(TextProperty);
        set => this.SetValue(TextProperty, value);
    }

    private Binding _textBinding;

    public Binding TextBinding
    {
        get => _textBinding;
        set => _textBinding = value;
    }

生成的 XAML 如下所示(在 MainWindowView 中,数据上下文设置为 MainWindowViewModel 的实例)

<d:Window.DataContext>
    <x:Type Type="local:MainWindowViewModel" />
</d:Window.DataContext>
<Grid>
    <DataGrid ItemsSource="{Binding Foos}" AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding FooDesignation}" />
            <local:CustomDataGridTextColumn Text="{Binding FooDesignation}" TextBinding="{Binding FooDesignation}" />
        </DataGrid.Columns>
    </DataGrid>
</Grid>

DataGridTextColumnBinding 属性可以毫无问题地绑定到 Foo (FooDesignation) 的属性,intellisense 也将此属性显示为一个选项。

我自己的 CustomDataGridTextColumn 的 Text 和 TextBinding 属性在绑定到同一个 FooDesignation 属性时会显示设计时和运行时错误。 Intellisense 向我展示了我的 MainWindowViewModel 的 Foos 属性作为选项(这很有意义,因为它显然没有继承 Foo 对象数据上下文)。

我的假设是它与 DataGridTextColumn 的 Binding 属性属于 Binding 类型这一事实有关,并且被配置为以某种方式运行可以。

我无法找到/理解这是如何实现的。任何人都可以对此有所了解吗?我的目标是让 Text/*TextBinding 属性的行为与 Binding 属性相同。

【问题讨论】:

    标签: c# wpf xaml data-binding user-controls


    【解决方案1】:

    您可以将ItemsSource 设置为任何IEnumerable,并且DataGrid 将列的绑定应用于在列的GenerateElementGenerateEditingElement 方法中创建的可视元素(控件):

        protected abstract FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem);
        protected abstract GenerateElement(DataGridCell cell, object dataItem);
    

    如您所见,这些方法接受从IEnumerable 检索的非类型化object。与所有其他绑定一样,使用反射解析实际属性值。这些列只是将绑定应用到生成的元素。

    如果您想创建自定义列,您应该从 DataGridBoundColumn 或其任何子级继承,并按原样使用现有的 Binding 属性。

    【讨论】:

    • 感谢您的评论。但是,它并没有完全回答我的问题。即使我(正确地)从 DataGridBoundColumn 继承,我自己的属性的行为方式仍然与 Binding 属性不同(即自动绑定到可枚举中的当前项,即使有智能感知支持)。 Telerik 的 DataGrid 还实现了一个 DataMemberBinding 属性,该属性的行为类似于 Binding 属性,因此我必须缺少一些东西才能以相同的方式实现它。
    • @GeorgeB:如何表现相同?在 Visual Studio 中?你在用 Resharper 还是别的什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多