我目前正在分析一些使用大量使用MultiDataTriggers的样式的XAML(每种样式8-10个多数据触发器,每个触发器有4-6个条件)。在考虑这个时,我正在考虑使用converter(或multi value converter)是否更有效,特别是因为无法调试MultiDataTriggers。
任何人都可以权威地说明如何编译MultiDataTriggers吗?我理解Conditions are ANDed在一起,编译的方式是短切还有特色吗?
多个MultiDataTriggers怎么样?它们是否被短路以使第一个完全满意导致评估停止?或者,如果有几个人满意,他们是否都会用最后一个获胜进行评估?
答案 0 :(得分:6)
Triggers are evaluated from top to bottom
。它适用于所有类型的触发器(Trigger,DataTrigger,MultiTrigger和MutliDataTrigger)。
多个MultiDataTriggers怎么样?它们是否短路 第一个完全满意导致评估停止?或者是 如果有几个人满意的话,他们都会用最后一个获胜进行评估?
如上所述,触发器从上到下进行评估。因此,如果第一个满足所有条件并不意味着不会评估进一步的触发。将评估应用于已更改属性的所有触发器,如果其中任何两个触发器在触发器内设置相同的属性,则last trigger always won
和overrides the property set by first trigger
。
<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>
当Test2
评估为真时,文字始终为IsEnable
。
任何人都可以权威地说明如何编译MultiDataTriggers吗?一世 理解条件是AND在一起,这是编译进去的 这种短切的特点是什么?
是的,MultiDataTrigger中有短切,即first condition evaluate to be false, second condition won't be checked
。此示例验证了这一点 -
<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>
在这两种情况下都会应用转换器,但如果IsEnabled
为false
,则为converter gets hit only once
,因为第一个条件的计算结果为false。但是,如果IsEnabled
为true
,则converter gets hit twice
,因为第一个条件成功满足。
答案 1 :(得分:1)
转换器允许调试和更复杂的逻辑,但他们还必须检查所有Bindings
并在每次Bindings
更改时调用外部函数。所以在几乎所有情况下它们都比触发器慢。触发器在第一个未满足的条件下停止。
所以我的答案是尽可能多地使用MutiDataTrigger,当你需要更多逻辑时,根据某些条件是否可能在其他地方重复,你可以选择实现额外的DependencyProperty
(当一些其他属性发生变化时会发生变化)或使用转换器。
例如,我有5个属性要绑定到:
IsChecked = A && B && (C || D || !E)
IsReadonly = !A && !B && (C || D || !E)
所以我会创建一个等于C || D || !E
的新属性F,当这三个中的一个发生更改时,请更新F
。现在我可以使用F
作为第三个触发器绑定路径。