ListBox change Opacity of unselected items when one is selected - wpf

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>

Related

How to change IsMouseOver style based on DataTrigger?

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>

On MouseOver of one item, need to change color of other items

Want two scenarios as below:
1. Default color as Green for all items
2. On mouse over, that one item only should be Green and all other items should turn to Yellow at same time.
<ListView Name="ListViewDisplay" Grid.Row="1" ItemsSource="{Binding ListItems}" Background="Green" >
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Background" Value="Green"/>
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True" />
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter Property="Background" Value="Green" />
</MultiTrigger.Setters>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="False" />
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter Property="Background" Value="Yellow" />
</MultiTrigger.Setters>
</MultiTrigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
</ListView>
With this code all items are always in yellow color.

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>

WPF Style DataGridHyperlinkColumn

I created a style for a hyperlink control:
<Style x:Key="MyHyperlink" TargetType="{x:Type Hyperlink}">
<Setter Property="Foreground" Value="{StaticResource HyperlinkBrush}" />
<Setter Property="IsEnabled" Value="{Binding IsEnabled,RelativeSource={RelativeSource AncestorType={x:Type FrameworkElement}}}" />
<Style.Triggers>
<Trigger Property="IsEnabled" Value="True">
<Setter Property="Cursor" Value="Hand"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True" >
<Setter Property="Foreground" Value="{StaticResource HyperlinkMouseOverBrush}" />
</Trigger>
</Style.Triggers>
</Style>
How can I use this style in a DataGridHyperlinkColumn?
The ElementStyle of this kind of column asks for a TextBlock style instead of an Hyperlink one...
<DataGridHyperlinkColumn EditingElementStyle="{StaticResource MyDataGridTextColumn}" ElementStyle="{StaticResource MyDataGridHyperlinkColumn}"
Header="WebSite" Binding="{Binding Site, NotifyOnValidationError=True,ValidatesOnDataErrors=True}" />
Remove the x:Key from your style and put it in DataGrid.Resources then it targets all Hyperlink controls within this DataGrid.

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