【问题标题】:Is there a way to use data-template inheritance in WPF?有没有办法在 WPF 中使用数据模板继承?
【发布时间】:2010-12-14 20:00:32
【问题描述】:

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

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

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

【问题讨论】:

    标签: wpf xaml datatemplate


    【解决方案1】:

    我发现做这种事情的唯一方法是:

    <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 上运行,而另一个不行
    • 我很困惑。该解决方案似乎是将内容堆叠在一起,而不是通过细微的调整(即继承)来减少代码。
    【解决方案2】:

    @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。这就是我们在这里实际所做的。

    希望这会有所帮助! :)

    【讨论】:

    • 我很困惑。该解决方案似乎是将内容堆叠在一起,而不是通过细微的调整(即继承)来减少代码。
    • 如果我想在 TemplateA 上将 TextBlock 上的 ForegroundBrush 更改为 Red 而不是在 TemplateB 上怎么办?
    • 您可以对 DataTemplate 应用本地样式,这正是这样做的。请记住,在运行时,一切基本上都只是扩展,并且适用常规样式/属性继承规则。
    • x:Shared:“当设置为 false 时,修改 WPF 资源检索行为,以便对属性资源的请求为每个请求创建一个新实例,而不是为所有请求共享同一个实例。” msdn.microsoft.com/en-us/library/aa970778(v=vs.110).aspx
    • 获得另一个好评、漂亮且优雅的解决方案,可显着减少 UI 重复。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-27
    • 2022-08-11
    • 1970-01-01
    • 2015-05-01
    • 1970-01-01
    • 2011-01-28
    相关资源
    最近更新 更多