【问题标题】:ControlTemplate with DataTrigger Vs. DataTemplate with DataTemplateSelectorControlTemplate 与 DataTrigger 对比。带有 DataTemplateSelector 的 DataTemplate
【发布时间】:2012-02-14 02:38:50
【问题描述】:

我有一个通用控件,它根据 ViewModel 中的 type 属性显示一个编辑器。目前它是使用ControlControlTemplateDataTrigger 实现的,就像这样 -

<Control
   x:Name="MainControl"
   Grid.Column="1"
   TargetUpdated="OnTargetUpdated">
        <Control.Style>
            <Style>
                <Style.Triggers>
                    <DataTrigger
                        Binding="{Binding Path=EditorType}"
                        Value="{x:Static view:EditorType.Bool}">
                        <Setter
                            Property="Control.Template"
                            Value="{StaticResource boolTemplate}" />
                    </DataTrigger>
                    <DataTrigger
                        Binding="{Binding Path=EditorType}"
                        Value="{x:Static view:EditorType.Text}">
                        <Setter
                            Property="Control.Template"
                            Value="{StaticResource textTemplate}" />
                    </DataTrigger>
                    <DataTrigger
                        Binding="{Binding Path=EditorType}"
                        Value="{x:Static view:EditorType.Integer}">
                        <Setter
                            Property="Control.Template"
                            Value="{StaticResource integerTemplate}" />
                    </DataTrigger>
                    ...
                    ....
                </Style.Triggers>
            </Style>
     </Control.Style>
</Control>

现在,可以像这样使用ContentPresenterDataTemplateDataTemplateSelector 来实现相同的功能-

<local:EditorTemplateSelector
    BoolEditorTemplate="{StaticResource boolTemplate}"
    TextEditorTemplate="{StaticResource textTemplate}"
    IntegerEditorTemplate="{StaticResource integerTemplate}"
    ...
    ....
    x:Key="EditorTemplateSelector">
</local:EditorTemplateSelector>

<ContentPresenter
    ContentTemplateSelector="{Binding Source={StaticResource EditorTemplateSelector}}"
    Content="{Binding}"
    TargetUpdated="OnTargetUpdated">
</ContentPresenter>

// Template selector returning appropriate template based on type

我觉得第二种方法,使用DataTemplateSelector 更好,但想知道你 -

  • 哪个更好,为什么?

  • 两者会有性能差异吗?

【问题讨论】:

  • 据我所知,第二种方式被认为是最佳实践。它也更具可读性,因为它不包含选择逻辑(应始终在 C# 中定义)。不过,我对性能点也很感兴趣。

标签: wpf datatemplate controltemplate datatrigger datatemplateselector


【解决方案1】:

我听说DataTemplateSelectors 如果它们基于的值发生变化,则不会更新模板,因此我通常不使用它们。

我的首选方法实际上是使用 DataTemplates。

<MyControl.Resources>
    <DataTemplate TargetType="{x:Type local:BooleanModel}">
        <local:BooleanView />
    </DataTemplate>
    <DataTemplate TargetType="{x:Type local:IntegerModel}">
        <local:IntegerView />
    </DataTemplate>
    ...
</MyControl.Resources>

其次,如果我想根据属性而不是对象类型来更改模板,我倾向于使用DataTriggers。这是因为如果该属性发生更改,PropertyChange 通知将自动告诉 UI 它已更改并更新模板。我不相信DataTemplateSelectors 会自动执行此操作。我也更喜欢在我的 XAML 中查看模板选择逻辑,而不是将其隐藏在 TemplateSelector 文件中,但这只是个人喜好。

我最后的选择是使用DataTemplateSelector。我几乎从不在 WPF 应用程序中使用它,尽管我经常在 Silverlight 中使用它,因为它不支持我使用隐式 DataTemplates 的首选方法(还)

我不知道两者之间有任何显着的性能差异,但如果有人可以告诉我,我会很感兴趣。

【讨论】:

  • 有趣,我几乎可以肯定这个问题是关于 WPF 的,只是出于好奇 - 他们是否修复了 SL4/5 中的隐式模板,因为我知道它们在以前的版本中不可用。
  • @Dmitry 我相信我做的最后一个 Silverlight 项目是在 4.0 中,当时隐式 DataTemplates 不起作用。我听说他们在 5.0 中工作,但还没有。
  • +1 表示“如果 DataTemplateSelectors 的值基于 chan,则不会更新模板”。我检查了这个,如果值发生变化,模板不会更新。谢谢。
  • 这并不总是正确的。如果您有一个 ContentPresenter 的 Content={Binding Path=SomeProp} 那么如果 SomeProp 更改 ContentPresenter 将再次向 TemplateSelector 询问模板。但是,如果 SomeProp 没有改变但该对象的属性发生了改变,那么您将不会再次调用模板选择器。
  • 这是来自@Rachel change-data-template-dynamically的datatemplateselector 示例
【解决方案2】:

这里有两个问题:)

  1. XAML(DataTriggers) 或代码TemplateSelector 中作出决定
  2. 您要覆盖整个Style 还是仅覆盖DataTemplate。在您的第一个示例中,您覆盖 Style,在第二个示例中 - DataTemplate

这是我的 2c:

我会坚持使用触发器,因为您将获得无与伦比的灵活性水平 - 新资源价格的新编辑器和 XAML 中的触发器 - 还有什么更好的?有一个与 DataTrigger 使用相关的潜在警告 - 它可能会导致数据泄漏。

谈到StyleDataTemplate 的选择,我再次坚持使用Style。它可能会更重一点的可视化树,但它会让你最终控制编辑器的外观。

特别是,某些属性只能使用StyleSetters 定义在Style 级别。 然后定义@DataTemplate 级别根本不起作用,因为您的DataTemplate 内容不是您的控制容器的直接子级(还有一个额外的级别-actula 控制)。如果你没有这样的属性,ControlTemplates 也不错,而且可能更快(?)。

【讨论】:

  • 谢谢 Dmitry,您能否提供有关“DataTrigger 导致数据泄漏”的更多详细信息?
  • @akjoshi - 抱歉,我无法给出准确的重现,这只是一种观察,我看到一些项目在减少触发器数量后受益匪浅。
【解决方案3】:

我建议答案更多是您认为control 是否必要。您可以通过control 获得一大堆功能,而DataTemplate 并不真正提供这些功能。您可以添加DependencyPropertieseventsfunctions 等。但是您需要这个吗?如果你不这样做,那么控制可能是矫枉过正。

【讨论】:

    【解决方案4】:

    我也不喜欢 DataTemplateSelector,但我想如果您的选择器评估包含不仅仅是类型检查,例如,您可以使用它们。 if x&gt;5 &amp;&amp; dayOfWeek==Tue &amp;&amp; isFullMoon(today) 然后是 template1。

    【讨论】:

    • 是的,如果需要复杂的逻辑,那么 DataTemplateSelector 很有用;虽然有些情况还是可以通过 MultiDataTrigger 实现的。
    猜你喜欢
    • 1970-01-01
    • 2018-05-08
    • 2011-03-04
    • 2011-01-06
    • 2012-04-17
    • 2011-10-09
    • 1970-01-01
    • 1970-01-01
    • 2011-12-30
    相关资源
    最近更新 更多