39

I encountered a situation where I can easily achieve the same functionality by using a MultiDataTrigger or, alternately, using a DataTrigger with a MultiBinding. Are there any substantive reasons to prefer one approach over the other?

With MultiDataTrigger:

<MultiDataTrigger>
    <MultiDataTrigger.Conditions>
        <Condition Binding="{Binding Path=SomePath}" Value="SomeValue"/>
        <Condition Binding="{Binding Path=SomeOtherPath, Converter={StaticResource SomeConverter}}" Value="SomeOtherValue"/>
    </MultiDataTrigger.Conditions>
    <MultiDataTrigger.EnterActions>
        <BeginStoryboard Storyboard="{StaticResource MyStoryboard}"/>
    </MultiDataTrigger.EnterActions>
</MultiDataTrigger>

With MultiBinding:

<DataTrigger Value="foo">
    <DataTrigger.Binding>
        <MultiBinding Converter="{StaticResource fooConv}"/>
            <Binding Path=SomePath/>
            <Binding Path=SomeOtherPath/>
        </MultiBinding>
    </DataTrigger.Binding>
    <DataTrigger.EnterActions>
        <BeginStoryboard Storyboard="{StaticResource MyStoryboard}"/>
    </DataTrigger.EnterActions>
</DataTrigger>
Rohit Vats
  • 79,502
  • 12
  • 161
  • 185
mcwyrm
  • 1,571
  • 1
  • 15
  • 27
  • Using a MultiDataTrigger would usually save you a multi-value converter. See [this question](http://stackoverflow.com/q/20990881/1136211) posted today. – Clemens Jan 08 '14 at 10:46
  • If one approach required significantly more effort than the other that would factor into my calculations. In this case either approach would involve using a converter - in actual fact I have the appropriate converters available and don't need to write them but if I did not it still wouldn't (in this case) make one approach more attractive than the other. – mcwyrm Jan 08 '14 at 10:50
  • Both your examples require a converter, so if you din't have them already implemented i would go with `MultiDataTrigger` solution since the `SomeConverter` is more likely to be used somewhere else and the `fooConv` is more likely not going to be used in other places. – Novitchi S Jan 08 '14 at 10:54
  • That appears to be the emerging consensus. The multiconverter I am using just does a `&&` on its values and I use it fairly frequently although I do vaguely wonder if I'm missing some easier approach. – mcwyrm Jan 08 '14 at 10:57

2 Answers2

16

Multibinding requires a converter for all but the rarest circumstances (using StringFormat).

MultiTrigger only requires a converter to get your binding results into booleans.

Gusdor
  • 14,001
  • 2
  • 52
  • 64
5

I would like to elaborate a little bit more.

For me, MultiBinding and MultiDataTrigger are fundamentally different and although in some situations you can use both to achieve the same functionality, it feels kind of like a hack to make both work the same way.

MultiDataTriggers should be used when you need more than one condition to be met separately so that you can do an action (set a property value, begin an animation etc). For example, you need A to be true and B to be false. Both of these conditions can by themselves be interpreted separately. It's the case of this question.

MultiBindings, on the other hand, should be used when you need more than one parameter to calculate a single output of your choice. This output would need to be of some value for you to set the property. For example, you will only change the property value if A equals B. This makes sense when you use the same style on multiple controls and A is a property of the control (say, the Text property of a TextBlock) and B is a single property from the View Model named "SelectedText". So a problem we might be trying to solve is this: among all the TextBlocks on my View, set the foreground of the one with the same Text as the property SelectedText from my View Model to blink (color changing animation).

In your example, I would use a MultiDataTrigger since your conditions can be evaluated separately. Otherwise your MultiValueConverter would only check for your second condition, ignoring the first one and would serve no real purpose for being a MultiDataTrigger really.

I'll leave the XAML for the example where I'd use the DataTrigger with MultiBinding that I mentioned above: (I assume you are using the MVVM pattern)

<Style TargetType="{x:Type TextBlock}" x:Key="SelectedTextStyle">
    <Setter Property="FontFamily" Value="Segoe UI Light"/>
    <Setter Property="FontSize" Value="24"/>
    <Setter Property="HorizontalAlignment" Value="Left"/>
    <Style.Triggers>
        <DataTrigger Value="True">
            <DataTrigger.Binding>
               <MultiBinding Converter="{StaticResource StringsToBooleanConverter}">
                    <Binding Path="SelectedText"/> <!--This is a property of the View Model-->
                    <Binding RelativeSource="{RelativeSource Self}" Path="Text"/> <!--This is the Dependency Property 'Text' of the TextBlock control-->
                </MultiBinding>
            </DataTrigger.Binding>
            <DataTrigger.EnterActions>
                <BeginStoryboard>
                    <Storyboard>
                        <ColorAnimation Storyboard.TargetProperty="Foreground.Color" Duration="0:0:2" From="Black" To="DarkOrange" AutoReverse="True" FillBehavior="HoldEnd" RepeatBehavior="Forever"/>
                    </Storyboard>
                </BeginStoryboard>
            </DataTrigger.EnterActions>
            <DataTrigger.ExitActions>
                <BeginStoryboard>
                    <Storyboard>
                        <ColorAnimation Storyboard.TargetProperty="Foreground.Color" Duration="0:0:0" From="DarkOrange" To="Black" FillBehavior="HoldEnd"/>
                    </Storyboard>
                </BeginStoryboard>
            </DataTrigger.ExitActions>
        </DataTrigger>
    </Style.Triggers>
</Style>
StayOnTarget
  • 11,743
  • 10
  • 52
  • 81
Daniel Marques
  • 683
  • 8
  • 17
  • I don't understand this at all. If I need A to be true and B to be false - the scenario for which you indicated a MultiDataTrigger would be most appropriate - then there is a value (the output) which can only be calculated by knowing A and B, which is the scenario in which you said a MultiBinding would be more appropriate. – mcwyrm Mar 22 '19 at 15:01
  • Except for this simple case (A == True && B == False) you don't need a converter to calculate the output. You can evaluate both of those separately. So, you can use MultiDataTrigger. On the other hand, if your test case is something like A > B, then you would need a converter and would need to evaluate both values at the same time. You need MultiBinding for that. – Daniel Marques Mar 22 '19 at 15:24
  • Is this based on anything aside from personal preference? – mcwyrm Mar 22 '19 at 16:12
  • No. Like most things in programming. – Daniel Marques Mar 22 '19 at 17:03