Monday, March 16 2009
A colleague of mine at the Lab recently asked how one would accomplish an OR condition in a MultiTrigger. After some thinking and looking around on the forums (see: here and here) a workable solution presented itself. MultiTrigger (and MultiDataTrigger) both take have a property called 'Conditions' of type ConditionCollection. Each Condition object within these ConditionCollections can be used in one of two ways:
- You can set the Property and Value properties to setup an ordinary property condition.
- You can set the Binding and Value properties to setup a data condition.
Now if you want to accomplish an or condition in either case you will actually use a MultiDataTrigger. The gotcha here is that we can use the Binding property of the Condition class in conjunction with a MultiValueConverter to get the desired behavior.
Consider the example where we want to change the background of a Button on either IsMouseOver or IsFocused. This could be accomplished using the following XAML:
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Value="True">
<Condition.Binding>
<MultiBinding Converter="{StaticResource BooleanOr}">
<Binding Path="IsMouseOver" RelativeSource="{RelativeSource self}" />
<Binding Path="IsFocused" RelativeSource="{RelativeSource self}" />
</MultiBinding>
</Condition.Binding>
</Condition>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter TargetName="Border" Property="Background" Value="Cyan" />
</MultiDataTrigger.Setters>
</MultiDataTrigger>
As you can see, we setup a MultiBinding to the Condition's Binding property and then use a simple MultiValueConverter that performs the or operation.
Another approach that I've considered (but which is considerably more work) is to create a subclass Condition called OrCondition which takes a set of conditions and updates itself accordingly when any of the child conditions change. It seems like there are a couple of places that might put up road blocks to this solution though. If you decided to take a stab at it, let me know!
All the source code for this example is available here.