在你回答之前:这个问题是关于WPF的ListView
控件(GridView
)。关于WPF的DataGrid
控件,ASP.NET的DataGrid
或ListView
控件或WinForm的DataGridView
或ListView
控件, 。它们听起来非常相似并经常混淆,但错误控制类型的答案对我来说无益,更重要的是浪费你写答案的时间,我认为不应该浪费。
我有一个ListView
控件,GridView
有几列绑定到我的视图模型的属性。通过指定GridViewColumn
(内联或通过资源),我可以轻松自定义CellTemplate
单元格的视觉外观。
现在我的视图模型上有一个特定的属性;它的类型是一个抽象基类,它的值可以是几种派生类型之一。每个派生类型在单元格中应该具有不同的DataTemplate
。幸运的是,GridViewColumn
有一个CellTemplateSelector
,它完全符合我的要求,但需要编写一些管道代码。但是查看DataTemplateSelector
的页面,它说:
请注意,如果您有不同类型的对象,则可以在DataTemplate上设置DataType属性。如果这样做,则无需创建DataTemplateSelector。 [...]有关详细信息,请参阅Data Templating Overview。
乌拉!无需编写管道代码。我的类型 不同,所以这看起来非常合适。但是,即使我定义DataTemplate
DataType
与GridViewColumn
匹配其中一个数据绑定列的特定派生类型(使用DisplayMemberBinding
的{{1}}绑定),没有效果。
我只想根据DataTemplate
中某个列的运行时类型显示不同的GridView
。 DataType
- 定位DataTemplates
与GridView
完全不兼容吗?有没有办法使用它们,还是我必须指定CellTemplateSelector
?也许有一种方法可以在DataTemplate
的{{1}}内指定多个GridViewColumn
,以便CellTemplate
属性有效?
答案 0 :(得分:7)
WPF允许您在逻辑树中插入ViewModels
等对象,而DataTemplate
可用于告诉WPF在绘制可视树时如何绘制指定的对象。
隐式DataTemplate
是仅DataTemplate
定义的DataType
(无x:Key
),并且只要WPF尝试呈现对象,它就会自动使用VisualTree中指定的类型。
所以,你可以使用
<Window.Resources>
<DataTemplate DataType="{x:Type local:ViewModelA}">
<local:ViewA />
</DataTemplate>
<DataTemplate DataType="{x:Type local:ViewModelB}">
<local:ViewB />
</DataTemplate>
<DataTemplate DataType="{x:Type local:ViewModelC}">
<local:ViewC />
</DataTemplate>
</Window.Resources>
告诉WPF使用ViewA绘制ViewModelA,使用ViewB绘制ViewModelB,使用ViewC绘制ViewModelC。
如果您只希望将此应用于GridView而不是整个Window,则可以指定<GridView.Resources>
(或<ListView.Resources>
,我不记得是哪一个)
应该注意的是,如果您使用DisplayMemberBinding
绑定列,它将呈现为TextBox
,其Text
值绑定到您的属性,这意味着它将呈现YourViewModel.ToString()
而不是尝试使用DataTemplate
在VisualTree中绘制ViewModel。
为避免这种情况,只需将CellTemplate
设置为ContentPresenter
,Content
属性绑定到ViewModel
,它就会使用隐式呈现ViewModel DataTemplates
<GridViewColumn Header="Some Header">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ContentPresenter Content="{Binding YourViewModelProperty}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
答案 1 :(得分:1)
DisplayMember*
属性的实现是垃圾,我不知道为什么他们认为绑定TextBlock
而不是ContentPresenter
是个好主意。
我建议使用attached property或具有相应属性的子类来覆盖它。您只需要创建一个DataTemplate
,其中ContentPresenter
的{{1}}绑定到目标属性,这将允许隐式Content
。然后,应将此延期DataTemplating
指定为列的DataTemplate
。