你如何同时使用一个数据类型,有针对性的DataTemplate与GridView的?针对性、数据类型、GridView、DataTemplate

2023-09-04 02:30:53 作者:你给我听好

之前你回答:这个问题是关于WPF的的ListView 控件(的GridView )。这是不会关于WPF的的DataGrid 控件,ASP.NET的的DataGrid 的ListView 控件,或者WinForm中的的DataGridView 的ListView 控件。他们都听起来非常相似,经常被混淆,但对于错误类型控件的回答是既无助于我,更重要的是浪费你走上写答案,我认为不应该浪费时间。

Before you answer: This question is about WPF's ListView control (with GridView). It is not about WPF's DataGrid control, ASP.NET's DataGrid or ListView controls, or WinForm's DataGridView or ListView controls. They all sound very similar and are often confused, but an answer for the wrong type of control is both unhelpful to me and more importantly a waste of the time you took to write the answer, which I believe should not be squandered.

我有一个的ListView 控制的GridView 有绑定到我的视图模型的属性多个列。我可以很容易地通过指定 CellTemplate (无论是在线还是通过资源定制 GridViewColumn 的细胞的外观)。

I have a ListView control with GridView that has several columns bound to my view-model's properties. I can easily customize the visual appearance of the GridViewColumn's cells by specifying a CellTemplate (either inline or via a resource).

现在我有我的视图模型的特定属性;其类型是一个抽象基类,它的值可以是多种派生类型之一。每个派生类型都应该有在细胞中不同的的DataTemplate 。幸运的是, GridViewColumn 有一个 CellTemplateSelector 这不正是我想要的,但需要写一些水暖code。但看的 DataTemplateSelector 它说:

Now I have a particular property on my view-model; its type is an abstract base class and its value can be one of several derived types. Each derived type should have a different DataTemplate in the cell. Luckily, GridViewColumn has a CellTemplateSelector which does exactly what I want, but requires writing some plumbing code. But looking at the page for DataTemplateSelector it says:

请注意,如果您有不同类型的对象,你可以设置在DataTemplate中的数据类型属性。如果你这样做,那么就没有必要创建一个DataTemplateSelector。 [...]欲了解更多信息,请参见数据模板概述。

Note that if you have objects of different types you can set the DataType property on the DataTemplate. If you do that then there is no need to create a DataTemplateSelector. [...] For more information, see Data Templating Overview.

万岁!无需编写水暖code。我种的是的不同,因此这似乎是一个完美的结合。但是,唉,我定义即使在的DataTemplate 数据类型的派生类型的数据绑定列中的一个特定的匹配,它没有任何效果(使用 GridViewColumn DisplayMemberBinding 绑定)。

Hurray! No need to write plumbing code. My types are different so this seems like a perfect fit. But alas, even after I defined a DataTemplate with a DataType that matches a specific derived type of one of the databound columns (bound using GridViewColumn's DisplayMemberBinding), it had no effect.

我只是想显示不同的的DataTemplate 按照一定的列在我的的GridView 的运行时类型。为数据类型 -targeted 的DataTemplates 简单地的GridView 不兼容?有没有一种方法使用它们,或必须采取指定 CellTemplateSelector ?或许有一种方法可以指定多个的DataTemplate S'的内线 GridViewColumn CellTemplate ,使数据类型属性将有效果?

I simply want to display a different DataTemplate according to the runtime type of a certain column in my GridView. Are DataType-targeted DataTemplates simply incompatible with GridView? Is there a way to use them, or must I resort to specifying a CellTemplateSelector? Perhaps there is a way to specify multiple DataTemplates inside GridViewColumn's CellTemplate, so that the DataType property will have an effect?

推荐答案

WPF允许你插入在逻辑树的对象,如的ViewModels ,而的DataTemplate 可以用来告诉WPF如何绘制可视化树时绘制指定对象。

WPF allows you to insert objects such as ViewModels in the Logical Tree, while a DataTemplate can be used to tell WPF how to draw the specified object when drawing the Visual Tree.

这是隐含的的DataTemplate 的DataTemplate 只能有一个数据类型定义(没有 X:关键),每当WPF试图呈现在VisualTree指定类型的对象,它会自动使用

An implicit DataTemplate is a DataTemplate that only has a DataType defined (no x:Key), and it will be used automatically whenever WPF tries to render an object of the specified type in the 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来绘制ViewModelA与ViewA,ViewModelB与ViewB,并ViewModelC与ViewC。

to tell WPF to draw ViewModelA with ViewA, ViewModelB with ViewB, and ViewModelC with ViewC.

如果你只希望这个应用,而不是整个窗口,以你的GridView,您可以指定&LT; GridView.Resources&GT; (或&LT ; ListView.Resources&GT; ,我不记得是哪一个)

If you only want this applied to your GridView instead of to the entire Window, you can specify <GridView.Resources> (or <ListView.Resources>, I can't remember which one)

应该注意的是,如果您使用的是绑定的列中的 DisplayMemberBinding ,它会呈现为文本框文本值绑定到你的财产,这意味着它将呈现 YourViewModel.ToString(),而不是试图绘制使用视图模型在VisualTree你的的DataTemplate

It should be noted that if you are binding your column using the DisplayMemberBinding, it will render as a TextBox with the Text value bound to your property, which means it will render YourViewModel.ToString() instead of trying to draw the ViewModel in the VisualTree using your DataTemplate.

要避免这种情况,只需设定 CellTemplate 来就像一个内容presenter 内容属性绑定到你的视图模型,它会利用渲染视图模型的隐含的DataTemplates

To avoid that, simply set the CellTemplate to something like a ContentPresenter with the Content property bound to your ViewModel, and it will render your ViewModel using your implicit DataTemplates

<GridViewColumn Header="Some Header">
    <GridViewColumn.CellTemplate>
        <DataTemplate>
            <ContentPresenter Content="{Binding YourViewModelProperty}" />
        </DataTemplate>
    </GridViewColumn.CellTemplate>
</GridViewColumn>