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

标签 wpf datagrid datatemplate datagridtemplatecolumn

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

现在,当使用内置的 DataGrid 时,ItemsSource 是 FooSet 对象的集合。我想要做的是设置五个模板列,它们都使用 FooTemplate 数据模板。但是,DataGrid 的模板列类型不允许我设置该列的数据源(例如 Foo1、Foo2 等),因此我最终复制模板,每列一次,只需将 Foo1.SomeProp 更改为 Foo2.SomeProp在模板的绑定(bind)中,这当然是荒谬的。但我一生都找不到怎么说“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。所有其他列都允许您设置一些绑定(bind)来执行此操作。我什至尝试子类化 DataGridTemplateColumn 来添加 DataSource,但没有走得太远(我的猜测是因为本身没有列,而是指示如何生成行中的单元格,但这只是猜测。)

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

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

中号

最佳答案

好问题,我会使用 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,但您也可以通过定义和引用一个键将其显式应用为每个 ContentControl 的 ContentTemplate,但无论如何您都知道这一点。


准系统子类化方法:

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>

关于wpf - 在内置的WPF DataGrid中,我可以为DataGridTemplateColumn设置数据源吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5854059/

相关文章:

c# - 模板中的 MVVM 绑定(bind)问题(特别是 Expander 控件的 HeaderTemplate)

c# - 无法将类型 'System.Linq.IQueryable<Database.Table>' 隐式转换为 'bool'

wpf - 获取 DataGrid WPF 中选定的行项目

c# - 与 Datatemplate 成员绑定(bind)

apache-flex - 如何使用 Flex Spark 数据网格显示多行列标题?

c# - WPF DataGrid 动态列绑定(bind)

.net - 在 MVVM 中,DataTemplates 是否将 Views 视为 UserControls 是 Views?

wpf - 从 WPF 中的代码弹出窗口不起作用(在调整大小和切换窗口时)

wpf - 带有 MVVM 模式的数字文本框

c# - 如何将信息从 ThreadPool.QueueUserWorkItem 传递回 UI 线程?