(多个)MultiDataTrigger与转换器的效率比较

8
我目前正在分析一些使用MultiDataTriggers的XAML样式(每个样式有8-10个多数据触发器,每个触发器有4-6个条件)。在考虑这个问题时,我正在考虑是否更有效地使用转换器(或多值转换器),特别是因为无法调试MultiDataTriggers。

有人能够权威地说明MultiDataTriggers是如何编译的吗?我了解到条件是ANDed together,这是否以这种方式编译,从而具有短路功能?
多个MultiDataTriggers呢?它们是否被短路,以便第一个完全满足引起评估停止?还是它们都被评估,如果有几个满足,则最后一个获胜?
2个回答

9

触发器从上到下进行评估。这适用于所有类型的触发器(Trigger,DataTrigger,MultiTrigger和MutliDataTrigger)。

多个MultiDataTriggers呢?它们是否被短路,以便第一个完全满足导致评估停止?还是它们都被评估,并且如果有几个满足,则最后一个获胜?

正如所述,触发器从上到下进行评估。因此,如果第一个触发器满足所有条件,并不意味着进一步的触发器将不被评估。应用于更改属性的所有触发器都将被评估,并且如果其中任何两个触发器在触发器内设置相同的属性,则最后一个触发器总是获胜覆盖由第一个触发器设置的属性

<TextBlock>
   <TextBlock.Style>
      <Style TargetType="TextBlock">
          <Style.Triggers>
             <DataTrigger Binding="{Binding IsEnable}" Value="True">
                <Setter Property="Text" Value="Test1"/>
             </DataTrigger>
             <DataTrigger Binding="{Binding IsEnable}" Value="True">
                <Setter Property="Text" Value="Test2"/>
             </DataTrigger>
           </Style.Triggers>
      </Style>
  </TextBlock.Style>
</TextBlock>

IsEnable为真时,文本始终为Test2


有人可以权威地说明MultiDataTrigger是如何编译的吗?我明白条件是ANDed在一起的,这个过程是以短路方式编译的吗?

是的,在MultiDataTrigger中采用了短路的方式,即如果第一个条件的评估结果为假,则不会检查第二个条件。这个示例验证了这一点 -

<TextBlock>
   <TextBlock.Style>
       <Style TargetType="TextBlock">
           <Style.Triggers>
               <MultiDataTrigger>
                   <MultiDataTrigger.Conditions>
                       <Condition Binding="{Binding IsEnable,
                             Converter={StaticResource SingleValueConverter}}" 
                                  Value="True"/>
                       <Condition Binding="{Binding IsEnable,
                             Converter={StaticResource SingleValueConverter}}"
                                  Value="True"/>
                    </MultiDataTrigger.Conditions>
                    <Setter Property="Text" Value="Test"/>
                </MultiDataTrigger>
          </Style.Triggers>
       </Style>
   </TextBlock.Style>
</TextBlock>

在两种情况下都会应用转换器,但是如果 IsEnabledfalse,那么 转换器仅被触发一次,因为第一个条件的结果为false。但是如果 IsEnabledtrue,那么 转换器被触发两次,因为第一个条件成功地满足了。


3
谢谢,好答案。像这样的例子就像链接到MSDN一样好 :) - slugster

2

转换器可以进行调试和更复杂的逻辑,但它们也必须检查它们的所有Bindings并在每次Bindings更改时调用外部函数。因此,在几乎所有情况下,它们比触发器慢。触发器会在第一个不满足条件的地方停止。

因此,我的建议是尽可能使用MutiDataTrigger,当需要更多逻辑时,根据是否可能在其他地方重复某些条件,您可以选择实现额外的DependencyProperty(当一些其他属性更改时会发生变化),或使用转换器。

例如,我有5个属性要绑定:

IsChecked = A && B && (C || D || !E)
IsReadonly = !A && !B && (C || D || !E)

于是我创建了一个新属性F,等于C || D || !E,当这三个中的一个发生变化时,更新F。现在我可以将F用作第三个触发器绑定路径。


谢谢你的回答,我不确定你是否理解我所问的全部含义?@Rohit的答案表明,我必须改用转换器,因为a)这些多数据触发器在一个已经非常缓慢的网格上; b)多数据触发器增加了绑定错误的风险,c)我想避免复杂的属性,因为绑定对象已经有足够的复杂属性,而且由于开发者编码不良,这些属性很容易变得缓慢。如果我要使用复杂属性,那么我可能需要使用专门为该特定绑定量身定制的转换器。 - slugster
但是话说回来,对于那些使用有限数量的多数据触发器但想简化其中条件的人来说,你的答案可能很有用。 - slugster

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