在这个假设的例子中,假设我有一个对象 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/