有没有办法在 WPF 中使用数据模板继承?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4443600/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 22:23:50  来源:igfitidea点击:

Is there a way to use data-template inheritance in WPF?

wpfxamldatatemplate

提问by Fragilerus

Is it possible to have DataTemplatecomposition or inheritance (similar to "BasedOn" in Styles)? There are 2 instances where I need that.

是否可以DataTemplate组合或继承(类似于样式中的“BasedOn”)?有 2 个实例我需要它。

  1. For inherited classes: I have a base class with several inherited classes. I don't want to duplicate the base class template in each of the derived class's DataTemplate.

  2. Different Views: for the same class I want to define a datatemplate, and then add to that template as appropriate. Ex. the base template will display the data in the object and then i want different templates that can perform different actions on the object, while displaying the data (inheriting the base template).

  1. 对于继承类:我有一个带有多个继承类的基类。我不想在每个派生类的DataTemplate.

  2. 不同的视图:对于同一个类,我想定义一个数据模板,然后根据需要添加到该模板中。前任。基本模板将显示对象中的数据,然后我想要不同的模板可以对对象执行不同的操作,同时显示数据(继承基本模板)。

回答by Liz

The only thing that I have found do to for this kind of thing is this:

我发现对这种事情所做的唯一一件事是:

<DataTemplate x:Key="BaseClass">
  <!-- base class template here -->
</DataTemplate>
<DataTemplate DataType="{x:Type app:BaseClass}">
  <ContentPresenter Content="{Binding}" 
                    ContentTemplate="{StaticResource BaseClass}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type app:DerivedClass}">
  <StackPanel>
    <ContentPresenter Content="{Binding}" 
                      ContentTemplate="{StaticResource BaseClass}"/>
    <!-- derived class extra template here -->
  </StackPanel>
</DataTemplate>

Basically this creates a "common" template that can be referenced using a key (BaseClass in this case). Then we define the real DataTemplate for the base class, and any derived classes. The derived class template would then add it's own "stuff".

基本上,这会创建一个“通用”模板,可以使用键(在本例中为 BaseClass)进行引用。然后我们为基类和任何派生类定义真正的 DataTemplate。派生类模板然后将添加它自己的“东西”。

There was some discussion about this on msdna while back, but no one came up with a better solution that I saw.

不久前msdn上有一些关于这个的讨论,但没有人想出我看到的更好的解决方案。

回答by Mark A. Donohoe

@Fragilerus and @Liz, actually I think I did come up with something better. Here's another approach that not only avoids the extra ContentPresenter binding, but also removes the need to have to apply a template within a template since the shared content is direct content which is set at compile-time. The only thing that happens at run-time would be the bindings you set inside the direct content. As such, this greatly speeds up the UI when compared to the other solution.

@Fragilerus 和 @Liz,实际上我想我确实想出了更好的方法。这是另一种方法,它不仅避免了额外的 ContentPresenter 绑定,而且不需要在模板中应用模板,因为共享内容是在编译时设置的直接内容。在运行时发生的唯一事情是您在直接内容中设置的绑定。因此,与其他解决方案相比,这大大加快了 UI。

<!-- Content for the template (note: not a template itself) -->
<Border x:Shared="False" 
        x:Key="Foo" 
        BorderBrush="Red" 
        BorderThickness="1" 
        CornerRadius="4">
    <TextBlock Text="{Binding SomeProp}" />
</Border>

<DataTemplate x:Key="TemplateA">
    <!-- Static resource - No binding needed -->
    <ContentPresenter Content="{StaticResource Foo}" /> 
</DataTemplate>

<DataTemplate x:Key="TemplateB">
    <!-- Static resource - No binding needed -->
    <ContentPresenter Content="{StaticResource Foo}" />
</DataTemplate>

Important: Make sure to use the x:Sharedattribute on your shared content or this will not work.

重要提示:请确保x:Shared在您的共享内容上使用该属性,否则这将不起作用。

The WPF'y Way

WPF的方式

The above said, this really isn't the most WPF-friendly way to do what you're after. That can be achieved using the DataTemplateSelector class which does exactly that... select's a data template based on whatever criteria you set.

上面说,这真的不是最适合 WPF 的方式来做你所追求的事情。这可以使用 DataTemplateSelector 类来实现,该类正是这样做的……选择一个基于您设置的任何条件的数据模板。

For instance, you could easily set one up that looks for your known data types and returns the same DataTemplate for both of them, but for all other types, it falls back to the system to resolve the DataTemplate. That's what we actually do here.

例如,您可以轻松设置一个来查找已知数据类型并为它们返回相同的 DataTemplate,但对于所有其他类型,它会回退到系统来解析 DataTemplate。这就是我们在这里实际做的事情。

Hope this helps! :)

希望这可以帮助!:)