How to change IsMouseOver style based on DataTrigger? - wpf

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>

Related

DataTrigger inside a MultiDataTrigger?

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>

How to multi-trigger on property and binding in wpf style

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>

Computed Setter Value based on existing value - WPF

Currently have a setup as below:
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="rectName" Property="Stroke" Value="Red"/>
<Setter TargetName="rectName" Property="StrokeThickness" Value="2"/>
</Trigger>
i.e. The trigger changes the Stroke and Thickness of a Rectangle to Red and 2 on MouseOver.
But this must happen only when the Rectangle's Stroke is Black (Few rectangles have transparent stroke)
Is there any way to put this condition on Setter? I'm looking at a less intrusive way of accomplishing this. Any leads?
Is there a construct something like below:
<Setter TargetName="rectName" Property="Stroke" Value="If Black Then Black Else Red"/>
Here this will work, note however this code will throw a stack overflow exception because of the change of the changing colors when you mouse over ie red black red black and so on :/ I would just suggest some other way to keep track of the rect state, maybe a variable in the ViewModel that keeps track of the state and and in the code replace:
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=Stroke}" Value="Black" />
With something like:
<Condition Binding="{Path=RectState}" Value="True" />
Otherwise this will crash :) (Sorry writing this in a rush)
<Rectangle Height="100" HorizontalAlignment="Left" Margin="182,152,0,0" Name="rectangle1" VerticalAlignment="Top" Width="200" >
<Rectangle.Style>
<Style TargetType="Rectangle">
<Setter Property="Fill" Value="Transparent" />
<Setter Property="Stroke" Value="Black" />
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsMouseOver}" Value="True" />
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=Stroke}" Value="Black" />
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="StrokeThickness" Value="2" />
<Setter Property="Stroke" Value="Red" />
</MultiDataTrigger.Setters>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
You can achieve this using MultiTrigger (code below not tested, but should be close enough)
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True" />
<Condition Property="Stroke" Value="Black" />
</MultiTrigger.Conditions>
<Setter TargetName="rectName" Property="Stroke" Value="Red" />
<Setter TargetName="rectName" Property="StrokeThickness" Value="2" />
</MultiTrigger>
</Style.Triggers>

ListBox change Opacity of unselected items when one is selected

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>

Change background on WPF Listview item when it's selected

I have a WPF Listview, and I have overridden the ListView.ItemTemplate to change the background color of the items on the ListViewItem.IsMouseOver event like so:
<AlternationConverter x:Key="BackgroundConverter">
<SolidColorBrush>White</SolidColorBrush>
<SolidColorBrush>
<SolidColorBrush.Color>
<Color A="242" R="242" G="242" B="242" />
</SolidColorBrush.Color>
</SolidColorBrush>
</AlternationConverter>
<Style x:Key="alternatingWithBinding" TargetType="{x:Type ListViewItem}">
<Setter Property="Height" Value="31"/>
<Setter Property="Background"
Value="{Binding RelativeSource={RelativeSource Self},
Path=(ItemsControl.AlternationIndex),
Converter={StaticResource BackgroundConverter}}"/>
<Style.Triggers>
<Trigger Property="ListViewItem.IsSelected" Value="True">
<Setter Property="ListViewItem.Background" Value="Yellow" />
</Trigger>
<Trigger Property="ListBoxItem.IsMouseOver" Value="True">
<Setter Property="ListBoxItem.Background" Value="Blue" />
</Trigger>
</Style.Triggers>
</Style>
What I'm trying to achieve is to have a different color when hovered over the already selected item (which is yellow). So on all the items it will be a Blue hover-over, and on the selected Yellow item, it'll be green.
I tried the below attempt, using MultiTrigger, but that didn't do the trick:
<Style x:Key="alternatingWithBinding" TargetType="{x:Type ListViewItem}">
<Setter Property="Height" Value="31"/>
<Setter Property="Background"
Value="{Binding RelativeSource={RelativeSource Self},
Path=(ItemsControl.AlternationIndex),
Converter={StaticResource BackgroundConverter}}"/>
<Style.Triggers>
<Trigger Property="ListViewItem.IsSelected" Value="True">
<Setter Property="ListViewItem.Background" Value="Yellow" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="ListBoxItem.IsMouseOver" Value="True"/>
<Condition Property="ListBoxItem.IsSelected" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="ListBoxItem.Background" Value="Green" />
</MultiTrigger>
<Trigger Property="ListBoxItem.IsMouseOver" Value="True">
<Setter Property="ListBoxItem.Background" Value="Blue" />
</Trigger>
</Style.Triggers>
</Style>
Any ideas?
Thanks.
Are the triggers are applied in order? It might work if you move the MultiTrigger to the bottom, then it will apply after the IsMouseOver Trigger.

Resources