在内置的WPF DataGrid中,我可以为DataGridTemplateColumn设置数据源吗?

2024-02-23

在这个假设的例子中,假设我有一个对象 FooSet,它有五个属性 Foo1、Foo2、Foo3、Foo4 和 Foo5,所有这些都是 Foo 类型,它本身有几个属性。最后,我有一个名为 FooTemplate 的 DataTemplate,它知道如何以图形方式显示 Foo 类型的对象。

现在,当使用内置的 DataGrid 时,ItemsSource 是 FooSet 对象的集合。我想要做的是设置五个模板列,它们都使用 FooTemplate 数据模板。但是,DataGrid 的模板列类型不允许我设置该列的数据源(例如 Foo1、Foo2 等),因此我最终复制模板,每列一次,只需将 Foo1.SomeProp 更改为 Foo2.SomeProp在模板的绑定中,这当然是荒谬的。但我一生都找不到怎么说“B 列使用 Foo2 作为数据源”。

这是一些伪 XAML 来展示我想要的......

<Resources>
    <DataTemplate TargetType="Foo">
        <StackPanel>
            <local:FooPropAControl Value="{Binding FooPropA}" />
            <local:FooPropBControl Value="{Binding FooPropB}" />
            <local:FooPropCControl Value="{Binding FooPropC}" />
        </StackPanel>
    </DataTemplate>
</Resources>

<DataGrid ItemsSource="{Binding MyItems}" AutoGenerateColumns="false">
    <DataGrid.Columns>
        <DataGridTemplateColumn DataSource="{Binding Foo1}" />
        <DataGridTemplateColumn DataSource="{Binding Foo2}" />
        <DataGridTemplateColumn DataSource="{Binding Foo3}" />
        <DataGridTemplateColumn DataSource="{Binding Foo4}" />
        <DataGridTemplateColumn DataSource="{Binding Foo5}" />
    </DataGrid.Columns>
</DataGrid>

即使我必须在列中显式指定模板,那也没关系。它将该列的数据源设置为 FooSet 的一个属性,这样我就可以只使用一个 DataTemplate。所有其他列都允许您设置一些绑定来执行此操作。我什至尝试子类化 DataGridTemplateColumn 以添加 DataSource 但没有走得太远(我的猜测是因为本身没有列,而是指示如何生成行中的单元格,但这只是猜测。)

现在我知道第 3 方 Xceed 网格可以让您准确指定这一点,但我希望有一个本机解决方案。

那么,怎么样?或者你可以吗?

M


好问题,我会使用ContentControl,代码仍然会有点膨胀,但它比复制整个模板要好,例如:

<DataGrid ItemsSource="{Binding EmpSets}">
    <DataGrid.Resources>
        <DataTemplate DataType="{x:Type obj:Employee}">
            <TextBlock>
                <Run Text="{Binding Name}"/>
                <Run Name="RunChan" Text=" - "/>
                <Run Text="{Binding Occupation}"/>
            </TextBlock>
        </DataTemplate>
    </DataGrid.Resources>
    <DataGrid.Columns>
        <DataGridTemplateColumn Header="Emp1">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <ContentControl Content="{Binding Emp1}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn Header="Emp2">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <ContentControl Content="{Binding Emp2}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <!-- ... -->
    </DataGrid.Columns>
</DataGrid>

在这里,我在资源中使用一个隐式 DataTemplate,但您也可以将其显式应用为ContentTemplate通过定义和引用一个键来控制每个 ContentControl,但无论如何你都知道这一点。


准系统子类化方法:

public class DataGridTemplateMemberColumn : DataGridTemplateColumn
{
    public static readonly DependencyProperty MemberPathProperty =
            DependencyProperty.Register("MemberPath", typeof(string), typeof(DataGridTemplateMemberColumn), new UIPropertyMetadata(null));
    public string MemberPath
    {
        get { return (string)GetValue(MemberPathProperty); }
        set { SetValue(MemberPathProperty, value); }
    }

    protected override System.Windows.FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
    {
        return GenerateContent(CellEditingTemplate, dataItem);
    }

    protected override System.Windows.FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
    {
        return GenerateContent(CellTemplate, dataItem);
    }

    private FrameworkElement GenerateContent(DataTemplate template, object dataItem)
    {
        var contentControl = new ContentControl();
        contentControl.ContentTemplate = template;
        if (MemberPath != null)
        {
            Binding binding = new Binding(MemberPath);
            binding.Source = dataItem;
            contentControl.SetBinding(ContentControl.ContentProperty, binding);
        }
        else
        {
            contentControl.Content = dataItem;
        }
        return contentControl;
    }
}
<DataGrid.Columns>
    <cex:DataGridTemplateMemberColumn MemberPath="Emp1" />
    <cex:DataGridTemplateMemberColumn MemberPath="Emp2" />
    <cex:DataGridTemplateMemberColumn MemberPath="Emp3" />
    <cex:DataGridTemplateMemberColumn MemberPath="Emp4" />
    <cex:DataGridTemplateMemberColumn MemberPath="Emp5" />
</DataGrid.Columns>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在内置的WPF DataGrid中,我可以为DataGridTemplateColumn设置数据源吗? 的相关文章

随机推荐