我为自定义类创建了一个DataTemplate,它应该用于显示文件类型的内容。
以下是放置在窗口资源字典中的示例:
<DataTemplate DataType="namespace:Handle">
<Border>
<TextBlock>This is a static data template</TextBlock>
</Border>
</DataTemplate>
DataGridTemplateColumn
CellTemplate
是否可以按类型而不是x:Key
引用给定的模板?
如果我使用像
这样的东西,它可以通过Key工作<DataGridTemplateColumn Header="The file name" CellTemplate="{StaticResource myTemplate }" />
没关系,但是我可以进行类型绑定吗?
DataGrid有没有自动生成的列,并不是每个列都应该由上面的模板模板化。
编辑:这是对@Anatoliy Nikolaev的回复:我认为你的回答并非我所期望的解决方案,因为我只是使用密钥。以下是概述行为的示例:
<DataTemplate x:Key="{x:Type system:Object}" DataType="{x:Type dataTemplateOnType:Handle}">
<Border>
<TextBlock>This is a static data template</TextBlock>
</Border>
</DataTemplate>
我可以参考:
<DataGridTemplateColumn Header="The file name" CellTemplate="{StaticResource {x:Type system:Object}}" />
这仍然只是一个复杂的密钥类型。
答案 0 :(得分:1)
不可能。
您的DataTemplate必须是实例化对象,才能将其分配给CellTemplate属性。这就是为什么你必须借助x:Key
来引用你的DataTemplate实例。
答案 1 :(得分:1)
这是一个有效的例子:
<Window.Resources>
<DataTemplate x:Key="{x:Type this:TestData}"
DataType="{x:Type this:TestData}">
<TextBox Text="{Binding Path=SomeProperty}"
Background="Aquamarine" />
</DataTemplate>
</Window.Resources>
...
<DataGridTemplateColumn Header="Test"
Width="*"
CellTemplate="{StaticResource {x:Type this:TestData}}" />
如果在CellTemplate
中写DynamicResource
,它将无效(正如我最初尝试过的那样)。
在这种情况下,这一行:
x:Key="{x:Type this:TestData}"
必然,没有她的例子将无法奏效。但是,如果您错过了Style
或DataTemplate
的密钥,则此构造:
<DataTemplate TargetType="{x:Type local:MyType}">
自动转换为:
<DataTemplate x:Key="{x:Type local:MyType}" TargetType="{x:Type local:MyType}">
这意味着Style/DataTemplate
将明确用于此类型的所有控件,因为在ResourceDictionaries
中不能是没有键的元素,而是这样做是为了简化结构MSDN
。
为什么在没有钥匙的情况下这种情况不起作用?我认为这是一个错误,或者有其他限制阻止他按原样工作,但它应该没有密钥。
答案 2 :(得分:0)
据我所知,DataGrid
不支持按模板列中的类型自动选择数据模板。但是,存在允许这种行为的解决方法。关键是在能够提供这种机制的数据模板中使用 ContentControl
作为嵌套元素。
<DataGrid ...>
<DataGrid.Resources>
<DataTemplate DataType="{x:Type local:MyType1}">
<!-- ...data template definition.-->
</DataTemplate>
<DataTemplate DataType="{x:Type local:MyType1}">
<!-- ...data template definition.-->
</DataTemplate>
<DataTemplate x:Key="DynamicTemplateColumnCellTemplate">
<ContentControl Content="{Binding}"/>
</DataTemplate>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTemplateColumn CellTemplate="{StaticResource DynamicTemplateColumnCellTemplate}"/>
</DataGrid.Columns>
</DataGrid>
如果您只想为单个列设置数据模板的范围,请将它们移到数据模板中。
<DataGrid ...>
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<DataTemplate.Resources>
<DataTemplate DataType="{x:Type local:MyType1}">
<!-- ...data template definition.-->
</DataTemplate>
<DataTemplate DataType="{x:Type local:MyType1}">
<!-- ...data template definition.-->
</DataTemplate>
</DataTemplate.Resources>
<ContentControl Content="{Binding}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
这种方法存在一个问题。如果 CanUserAddRows
是 True
并且您使用具有无参数构造函数的类型集合,则 DataGrid
将添加一个附加项,该项不匹配任何数据模板类型,因此显示为通过 ToString
的纯文本,这不是您想要的。
这个晦涩的项目来自 DataGrid
中的一个内部属性。它是这样定义的 (reference source):
internal static object NewItemPlaceholder
{
get { return _newItemPlaceholder; }
}
private static object _newItemPlaceholder = new NamedObject("DataGrid.NewItemPlaceholder"); // Used as an alternate data item to CollectionView.NewItemPlaceholder
为了正确显示该项目,您必须检测该项目,例如使用样式触发器,但它定义为 internal
,因此您不能直接引用它。 marukp 扩展是通过反射访问它的一种方式。尽管这种方法将来可能会失效并且有些脏,但目前它很容易解决。
public class DataGridNewItemPlaceholderExtension : MarkupExtension
{
public override object ProvideValue(IServiceProvider serviceProvider)
{
return typeof(DataGrid).GetProperty("NewItemPlaceholder", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null);
}
}
使用这个标记扩展,我们可以在数据模板中添加一个DataTrigger
,将嵌套的Content
的{{1}}设置为空字符串,这样看起来就像默认的新项行。
ContentControl
您甚至可以为新项目占位符定义单独的数据模板。
<DataGrid ... CanUserAddRows="True">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<DataTemplate.Resources>
<DataTemplate DataType="{x:Type local:MyType1}">
<!-- ...data template definition.-->
</DataTemplate>
<DataTemplate DataType="{x:Type local:MyType1}">
<!-- ...data template definition.-->
</DataTemplate>
</DataTemplate.Resources>
<ContentControl x:Name="ContentControl" Content="{Binding}" />
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding}" Value="{local:DataGridNewItemPlaceholder}">
<Setter TargetName="ContentControl" Property="Content" Value="{x:Static system:String.Empty}" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>