Efficiency of (multiple) MultiDataTrigger vs. Converter
Asked Answered
L

2

8

I'm currently analyzing some XAML that uses style that make extensive use of MultiDataTriggers (8-10 multi data triggers per style, with 4-6 conditions per trigger). When looking at this I'm considering whether it would be more efficient to use a converter (or multi value converter), especially as MultiDataTriggers cannot be debugged.

Can anyone authoritatively state how MultiDataTriggers are compiled? I understand that the Conditions are ANDed together, is this compiled in such a way that short cutting is featured?

What about multiple MultiDataTriggers? Are they short circuited so that the first one fully satisfied causes evaluation to stop? Or are they all evaluated with the last one winning if several are satisfied?

Linet answered 10/11, 2013 at 11:7 Comment(0)
H
9

Triggers are evaluated from top to bottom. It holds true for all sorts of triggers (Trigger, DataTrigger, MultiTrigger and MutliDataTrigger).

What about multiple MultiDataTriggers? Are they short circuited so that the first one fully satisfied causes evaluation to stop? Or are they all evaluated with the last one winning if several are satisfied?

As stated triggers are evaluated from top to bottom. So, in case first one satisfy all conditions doesn't mean further triggers won't be evaluated. All triggers applied on changed property are evaluated and in case any two of them are setting same property inside a trigger then last trigger always won and 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>

Text will always be Test2 when IsEnable evaluates out to be true.


Can anyone authoritatively state how MultiDataTriggers are compiled? I understand that the Conditions are ANDed together, is this compiled in such a way that short cutting is featured?

Yeah, short cutting is featured in MultiDataTrigger i.e. if first condition evaluate to be false, second condition won't be checked. This sample validates this -

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

On both conditions a converter is applied but in case IsEnabled is false, converter gets hit only once because first condition evaluates out to be false. But in case IsEnabled is true, converter gets hit twice since first condition is meet successfully.

Hosbein answered 10/11, 2013 at 11:27 Comment(3)
Thanks, good answer. Examples like this are as good as links to MSDN :)Linet
I cannot reproduce this (in .NET 8). If the first condition evaluates to false, the second condition will still be checked. However in my case, both conditions are bound to different properties (not the same as in your example, which would IMO make little sense anyway).Rapper
Looking at the source code for MultiDataTrigger, it seems like all conditions are evaluated and AND'ed.Rapper
G
2

Converters allow debugging and more complex logics but they also have to check all their Bindings and call an external function each time one of their Bindings change. So they are slower than Triggers in almost all cases. Triggers stop at the first not-met-condition.

So my answer is to go with MutiDataTrigger as much as you can, when you needed more logic, depending on whether it's possible that some conditions are repeated elsewhere or not, you can choose to implement an extra DependencyProperty (which changes when some few other properties change) or to use a converter.

For example I have 5 properties which I want to bind to:

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

so I would create a new property F equal to C || D || !E and when one of these three changes, update F. now I can use F as the third trigger binding path.

Gurdwara answered 10/11, 2013 at 11:40 Comment(2)
Thanks for the answer, I'm not sure you understood the full implications of what I was asking? @Rohits answer shows that I'll have to change to a converter because a) these multidatatriggers are on a grid which is already diabolically slow; b) multidatatriggers increase the risk of binding errors, and c) I want to avoid complex properties because the bound objects already have enough of these and it's easy for these to become slow due to dev's coding badly. If I was to use complex properties then I might as well use a converter that is tailored specifically for that particular binding.Linet
But having said that your answer could be good for someone who is using a limited amount of multidatatriggers but wants to simplify the conditions in them.Linet

© 2022 - 2024 — McMap. All rights reserved.