有没有一种在WPF中使用数据模板继承的方法?

53

是否有可能进行组合或继承(类似于样式中的“BasedOn”)? 我有两个需要这样做的情况。

  1. 对于继承类:我有一个带有多个继承类的基类。我不想在每个派生类的中重复基类模板。

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

2个回答

52

我所发现的解决这种问题的唯一方法是:

<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>

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

以前在msdn上有一些关于此的讨论,但我没有看到有人提出更好的解决方案。


+1 因为你的代码可以在 Windows Phone 上运行,而另一个不能。 - NadaNK
1
我感到困惑。这个解决方案似乎是将内容叠加在一起,而不是通过微调(即继承)来减少代码量。 - Scott Nimrod

24

@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>

重要提示:务必在共享内容上使用x:Shared属性,否则此方法将无效。

WPF的方式

虽然如上所述,这并不是实现你想要的功能最友好的WPF方式。可以使用DataTemplateSelector类来实现这一点,它会根据设置的任何条件选择数据模板。

例如,您可以轻松地设置一个模板,它查找已知的数据类型,并为这两种类型返回相同的DataTemplate,但对于其他所有类型,则回退到系统以解析DataTemplate。这就是我们在这里实际执行的操作。

希望这可以有所帮助! :)


2
我感到困惑。这个解决方案似乎是将内容堆叠在一起,而不是通过微小的调整(例如继承)来减少代码量。 - Scott Nimrod
1
你可以为 DataTemplate 应用本地样式,以实现这一点。请记住,在运行时,所有内容基本上都会被展开,常规的样式/属性继承规则也适用。 - Mark A. Donohoe
x: Shared: "当设置为 false 时,修改 WPF 资源检索行为,以便对标记的资源的请求为每个请求创建一个新实例,而不是为所有请求共享同一实例。" - juFo
1
获得另一个赞,优雅的解决方案显著减少了UI重复。 - The Cookies Dog
一个实际的DataTemplate(或ControlTemplate)原则上可以代替作为资源定义的Control,如果需要的话。剩下的原则(在子类特定模板内实例化它)将按照这个答案提出的方式完成。 - heltonbiker
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接