I want to change 2 Properties on 2 different conditions using Multi-/DataTrigger.
I have 1 Button which changes its IsEnabled Property when ValidationRule returns an error.
I also want to change the Command Property of this Button but on other conditions.
<Button Content="Save">
<Button.Style>
<Style TargetType="Button" BasedOn="{StaticResource MaterialDesignFlatButton}">
<Setter Property="IsEnabled" Value="False" />
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=(Validation.HasError), ElementName=FirstNameBox}" Value="False" />
<Condition Binding="{Binding Path=(Validation.HasError), ElementName=LastNameBox}" Value="False" />
[...]
</MultiDataTrigger.Conditions>
<Setter Property="IsEnabled" Value="True" />
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
Now I want to implement another Trigger which changes the Binding of the Command Property when anoither Propertie's Binding equals to XY.
So i need to implement this next to the Datatrigger above.
<Setter Property="Command" Value="{Binding CreateEmployeeCommand}" />
<DataTrigger Binding="{Binding CurrentManageMode}" Value="2">
<Setter Property="Command" Value="{Binding EditEmployeeCommand}" />
</DataTrigger>
So is it even possible to have 2 Triggers at the same time?
Okay, i fixed it adding another Trigger just in Style.Triggers.
I didn't tried this cuz many Controls/Properties doesn't allow multiple Content.
<Button.Style>
<Style TargetType="Button" BasedOn="{StaticResource MaterialDesignFlatButton}">
<Setter Property="IsEnabled" Value="False" />
<Setter Property="Command" Value="{Binding CreateEmployeeCommand}" />
<Style.Triggers>
<DataTrigger Binding="{Binding CurrentManageMode}" Value="2">
<Setter Property="Command" Value="{Binding EditEmployeeCommand}" />
</DataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=(Validation.HasError), ElementName=FirstNameBox}" Value="False" />
<Condition Binding="{Binding Path=(Validation.HasError), ElementName=LastNameBox}" Value="False" />
</MultiDataTrigger.Conditions>
<Setter Property="IsEnabled" Value="True" />
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
Related
This code below changes the background on all states. How to change background to blue only when both IsMouseOver and DataTrigger is true?
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" TargetName="Target1" Value="Red" />
</Trigger>
<DataTrigger Binding = "{Binding ElementName = Import, Path = IsEnabled}" Value="true">
<Setter Property="Background" TargetName="Target1" Value="Blue" />
</DataTrigger>
</ControlTemplate.Triggers>
You can do a MultiDataTrigger. Something like:
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsEnabled}" Value="True" />
<Condition Binding="{Binding IsMouseOver}" Value="True" />
</MultiDataTrigger.Conditions>
<Setter Property="...." Value="...." />
</MultiDataTrigger>
I have datagrid in my view and I am trying to trigger a style for the DataGridRowHeader so that it has a particular background when both of the following are true:
IsDirty=True (Property on the DataContext of the row)
IsRowSelected=True (Property on the DataGridRowHeader)
How do I write a multi-trigger that triggers for the above paired conditions as my following style code throws InvalidOperationException/{"Must have non-null value for 'Property'."}:
<Style x:Key="DataGridStandardRowHeaderStyle" TargetType="DataGridRowHeader">
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Binding="{Binding IsDirty}" Value="True" />
<Condition Property="IsRowSelected" Value="True" />
</MultiTrigger.Conditions>
<Setter Property="Background" Value="LightYellow" />
</MultiTrigger>
</Style.Triggers>
</Style>
Kindly help me out.
The mistake in my style code finally got across to me and the correct one that now works for me is given below:
<Style x:Key="DataGridStandardRowHeaderStyle" TargetType="DataGridRowHeader">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsDirty}" Value="True" />
<Condition Binding="{Binding IsRowSelected, RelativeSource={RelativeSource Self}}" Value="True" />
</MultiDataTrigger.Conditions>
<Setter Property="Background" Value="LightYellow" />
</MultiDataTrigger>
</Style.Triggers>
</Style>
The following triggers work almost as expected:
<Style.Triggers>
<Trigger Value="True" Property="IsSelected">
<Setter Property="Foreground" Value="White" />
</Trigger>
<DataTrigger Value="True" Binding="{Binding UpdateSourceTrigger=PropertyChanged, Converter={StaticResource InUseConverter}}">
<Setter Property="Foreground" Value="OrangeRed" />
</DataTrigger>
</Style.Triggers>
After loading the view, the colors are correct.
Then I execute an async taks en when it has finished I give the propertychanged on the object that has the binding to my datagrid-row.
But why is the DataTrigger not fired (I have to refresh the view to see the effect)?
EDIT:
My problem is that I don't now which property I have to give the PropertyChanged.
Some details about the datagrid (Projects is an ObservableCollection):
DataGrid SelectedItem="{Binding Project}" ItemsSource="{Binding Projects}">
The property of object Project that the binding must use is:
Project.Variants[0].InUse
I tried also the triggers:
<DataTrigger Value="True" Binding="{Binding Path=Variants[0].InUse, Converter={StaticResource NotNullConverter}}">
<DataTrigger Value="True" Binding="{Binding Path=., Converter={StaticResource InUseConverter}}">
In the view model I have tried after Project.Variants[0].InUse = null;:
Project.OnPropertyChanged("InUse");
Project.Variants[0].OnPropertyChanged("InUse");
raisePropertyChanged("Project.Variants[0].InUse");
raisePropertyChanged("Variants[0].InUse");
raisePropertyChanged("Projects");
raisePropertyChanged("Project");
raisePropertyChanged("InUse");
At last it works using:
<DataTrigger Value="True" Binding="{Binding Path=Variants[0].InUse, Converter={StaticResource NotNullConverter}}">
<Setter Property="Foreground" Value="OrangeRed" />
</DataTrigger>
Project.Variants[0].OnPropertyChanged("InUse");
Try to set Foreground property in your style to change it dynamically at runtime
<Setter Property="Foreground" Value="White"/>
<Style.Triggers>
<Trigger Value="True" Property="IsSelected">
<Setter Property="Foreground" Value="White" />
</Trigger>
<DataTrigger Value="True" Binding="{Binding UpdateSourceTrigger=PropertyChanged, Converter={StaticResource InUseConverter}}">
<Setter Property="Foreground" Value="OrangeRed" />
</DataTrigger>
</Style.Triggers>
I have a list box with defined DataTemplate, Style and ItemContainerStyle.
This list box have SelectionMode="Single".
Initially all Items have Opacity="0.7", when Item selected I make it Opacity="1"
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Style.Setters>
<Setter Property="Opacity" Value="0.7"/>
</Style.Setters>
<Style.Triggers>
<DataTrigger Binding="{Binding IsEventLocked}" Value="False">
<Setter Property="IsEnabled" Value="False"/>
<Setter Property="Opacity" Value="0.2"/>
</DataTrigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Opacity" Value="1"/>
</Trigger>
</Style.Triggers>
</Style>
But I also need make all other (unselected) items with Opacity="0.2" until Selected item will be unselected.
In short: [Initial (Opacity=0.7)]->[ItemSelected = {(SelectedItem:Opacity=1), (All Unselected items: Opacity=0.2)}]->[Item Deselected (SelectedItem==null) =(Opasity=0.7)]
Thanks for syggestions and ideas!
Trigger on: Selection being there && not being selected oneself.
This should do:
<Style TargetType="ListBoxItem">
<Setter Property="Opacity" Value="0.7" />
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsSelected, RelativeSource={RelativeSource Self}}"
Value="false" />
<Condition
Binding="{Binding SelectedItems.Count, RelativeSource={RelativeSource AncestorType=ListBox}}"
Value="1" />
</MultiDataTrigger.Conditions>
<Setter Property="Opacity" Value="0.2" />
</MultiDataTrigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Opacity" Value="1" />
</Trigger>
</Style.Triggers>
</Style>
When using Normal trigger I can get the functionality to work easily.
But when I use MultiDataTrigger I cannot get it to work.
This does not work.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="Brush_GridBackground" TargetType="{x:Type Grid}">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding ElementName=cb_BackgroundColor, Path=SelectedItem.Tag}" Value="Red" />
<Condition Binding="{Binding ElementName=cb_BackgroundColor, Path=SelectedItem.Tag}" Value="White" />
<Condition Binding="{Binding ElementName=cb_BackgroundColor, Path=SelectedItem.Tag}" Value="Black" />
<Condition Binding="{Binding ElementName=cb_BackgroundColor, Path=SelectedItem.Tag}" Value="Blue" />
<Condition Binding="{Binding ElementName=cb_BackgroundColor, Path=SelectedItem.Tag}" Value="Green" />
</MultiDataTrigger.Conditions>
<Setter Property="Background" Value="{Binding ElementName=cb_BackgroundColor, Path=SelectedItem.Tag}" />
</MultiDataTrigger>
</Style.Triggers>
</Style>
This works
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="Brush_GridBackground" TargetType="{x:Type Grid}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=cb_BackgroundColor, Path=SelectedItem.Tag}" Value="Red">
<Setter Property="Background" Value="{Binding ElementName=cb_BackgroundColor, Path=SelectedItem.Tag}" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=cb_BackgroundColor, Path=SelectedItem.Tag}" Value="White">
<Setter Property="Background" Value="{Binding ElementName=cb_BackgroundColor, Path=SelectedItem.Tag}" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=cb_BackgroundColor, Path=SelectedItem.Tag}" Value="Black">
<Setter Property="Background" Value="{Binding ElementName=cb_BackgroundColor, Path=SelectedItem.Tag}" />
</DataTrigger>
</Style.Triggers>
</Style>
Howcome?
A MultiDataTrigger is like using an AND statement with your Triggers, so you are basically saying if the Tag is equal to Red, White, Black, Blue, and Green, then apply the following style, however the tag can only equal to one of those values, so the trigger is always going to end up as False.
Having Multiple triggers, such as your working code, is the syntax I use if I want to OR the triggers.