WPF DataTrigger not working On ComboBox? - wpf

I've got the following pure XAML:
<DockPanel>
<ComboBox Name="combo" Height="24" Width="60">
<Border Background="Gray" Padding="20,10">
<Border.Style>
<Style TargetType="Border">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=combo, Path=IsDropDownOpen}" Value="True">
<Setter Property="Background" Value="Red"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
</ComboBox>
<TextBlock Text="{Binding ElementName=combo, Path=IsDropDownOpen}"></TextBlock>
</DockPanel>
I would expect the datatrigger to change the background colour of the border object to red as soon as the combobox is opened, but instead nothing happens.

Since you have set the background property directly on the ComboBox the trigger is not going to override that value.
This behavior is explained on MSDN.
You have to set it in the style instead like this:
<Border Padding="20,10">
<Border.Style>
<Style TargetType="Border">
<Setter Property="Background" Value="Gray" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=combo, Path=IsDropDownOpen}" Value="True">
<Setter Property="Background" Value="Red"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>

Related

change properties inside datatemplate of listboxItem if selected

I have the following style:
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock x:Name="Text" Text="{Binding Name}" Margin="0, 5" FontSize="16"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
I want to change the foreground color of "Text" if the "ListBoxItem" is selected. I know from here: Change WPF DataTemplate for ListBox item if selected how to change the DataTemplate. but since I just want to change colors, this solution makes unnecessary duplication in codd - It would be a greater problem if my DataTemplate would be very complex and long.
How do I achieve change of a single property of an object inside the DataTemplate?
If you actually want the same item template always (whether the item is selected or not), but you want a different foreground color when the item is selected, that's easy. Don't set the ContentTemplate in a trigger, because ContentTemplate doesn't change. Just set the foreground color with a trigger. If you don't mess with the foreground color in the template, it will inherit whatever the ListBoxItem has for that property.
<Style TargetType="ListBoxItem">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock
x:Name="Text"
Text="{Binding Name}"
Margin="0, 5"
FontSize="16"
/>
</DataTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
A more elaborate version of the same style:
<Style TargetType="ListBoxItem">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Ellipse
Height="12"
Width="12"
VerticalAlignment="Center"
x:Name="Ellipse"
Fill="Yellow"
Stroke="DeepSkyBlue"
StrokeThickness="1"
/>
<TextBlock
x:Name="Text"
Text="{Binding Name}"
Margin="5,5,0,5"
FontSize="16"
/>
</StackPanel>
<DataTemplate.Triggers>
<DataTrigger
Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=ListBoxItem}}"
Value="True"
>
<Setter
TargetName="Ellipse"
Property="Stroke"
Value="Orange"
/>
<Setter
TargetName="Ellipse"
Property="StrokeThickness"
Value="3"
/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>

Set Image border when item is selected in a listbox

I ve been playing with this for a while and I can't make it work. Basically, I have a listbox with an image and a label. What I'd like is to change the color of the border of the image if that item is selected (the listbox is set to multiple selection)
This is I have so far...
<DataTemplate x:Key="ListBox_DataTemplate">
<Grid HorizontalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="220"/>
</Grid.RowDefinitions>
<Border x:Name="thumbBorder" BorderThickness="8"
CornerRadius="8">
<Border.Style>
<Style TargetType="Border">
<Style.Triggers>
<DataTrigger Binding="{Binding isSelected,
ElementName=lb_images}" Value="True">
<Setter Property="BorderBrush
Value="SteelBlue"/>
</DataTrigger>
<DataTrigger Binding="{Binding isSelected,
ElementName=lb_images}" Value="False">
<Setter Property="BorderBrush"
Value="Yellow"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<Image Width="170" Height="190" Source="{Binding Thumbnail}"
HorizontalAlignment="Center"
VerticalAlignment="Top"
x:Name="thumb"/>
</Border>
However, nothing happens when I select the item. IIm really stuck, so any ideas would be welcome.
Thanks
Your DataTrigger should use a RelativeSource Binding to the ListBoxItem container element, and use the correct property path IsSelected:
<DataTemplate x:Key="ListBox_DataTemplate">
<Border BorderThickness="8">
<Border.Style>
<Style TargetType="Border">
<Setter Property="BorderBrush" Value="Yellow"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected,
RelativeSource={RelativeSource AncestorType=ListBoxItem}}"
Value="True">
<Setter Property="BorderBrush" Value="SteelBlue"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<Image Source="{Binding Thumbnail}"/>
</Border>
</DataTemplate>

Color Style Textblock

I have this textblock with default foreground color is white
<TextBlock Text="First Cmd" Grid.Row="0" TextAlignment="Center" Margin="4" TextWrapping="Wrap" Foreground="White" Style="{DynamicResource ABC}">
<TextBlock.InputBindings>
<MouseBinding Command="{Binding AAA}" MouseAction="LeftClick" />
</TextBlock.InputBindings>
</TextBlock>
When the mouse is over the textblock, the forground color must change in black, but this Style doesn't work. Why ?
<Style x:Key="ABC" TargetType="{x:Type TextBlock}">
<Style.Triggers>
<Trigger Property ="IsMouseOver" Value="True">
<Setter Property= "Foreground" Value="Black">
</Trigger>
</Style.Triggers>
</Style>
You set the Foreground for TextBlock locally, so the Trigger setter cannot override that. You need to use a Style setter to set the initial Foreground:
<Style x:Key="ABC" TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="White"/>
<Style.Triggers>
<Trigger Property ="IsMouseOver" Value="True">
<Setter Property= "Foreground" Value="Black">
</Trigger>
</Style.Triggers>
</Style>
The Foreground="White" should be removed from the <TextBlock ....
Understand more about Dependency Property Value Precedence.

Change WPF StackPanel background color when an element in the panel has focus

If I have a set of controls within a StackPanel, is there a generic way to change the background of the stackpanel when any control within the StackPanel gains focus? (and obviously switch the background back when no control in the StackPanel has focus). The following code works for me, but it would be nice to have a generic way to accomplish this task versus having to list each control in every StackPanel in my page.
Thanks!
<StackPanel Margin="5">
<StackPanel.Style>
<Style TargetType="{x:Type StackPanel}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsFocused, ElementName=chkOccupiedByMortgagor}" Value="true">
<Setter Property="Background" Value="Gray" />
<Setter Property="Opacity" Value=".5" />
</DataTrigger>
<DataTrigger Binding="{Binding IsFocused, ElementName=chkOccupiedByNewOwner}" Value="true">
<Setter Property="Background" Value="Gray" />
<Setter Property="Opacity" Value=".5" />
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<CheckBox Margin="2" x:Name="chkOccupiedByMortgagor">Mortgagor</CheckBox>
<CheckBox Margin="2" x:Name="chkOccupiedByNewOwner">New Owner</CheckBox>
<CheckBox Margin="2" x:Name="chkOccupiedByTenant">Tenant</CheckBox>
<CheckBox Margin="2" x:Name="chkOccupiedByUnknownOccupant">Unknown Occupant</CheckBox>
</StackPanel>
Yes. You can do that. Just use IsKeyboardFocusWithin property for the trigger, like this:
<StackPanel Margin="5">
<StackPanel.Style>
<Style TargetType="{x:Type StackPanel}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsKeyboardFocusWithin}" Value="True">
<Setter Property="Background" Value="Gray" />
<Setter Property="Opacity" Value=".5" />
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<CheckBox Margin="2">Mortgagor</CheckBox>
<CheckBox Margin="2">New Owner</CheckBox>
<CheckBox Margin="2">Tenant</CheckBox>
<CheckBox Margin="2">Unknown Occupant</CheckBox>
</StackPanel>
Do remember though, that you need to tell the trigger to look for the property in the same element, hence, RelativeSource={RelativeSource Self}. Alternatively, you can name the stack panel and use this xaml too:
<StackPanel Margin="5" x:Name="stackPanel">
...
<DataTrigger Binding="{Binding ElementName=stackPanel, Path=IsKeyboardFocusWithin}" Value="True">
...

Can't update textbox property using DataBinding

I have a custom window which have two depencency properties: Boolean? ValidationStatus, and string ValidationMessage. Binding these properties works fine but trigger doesn't seem to be triggered when these values change. What am I doing wrong?
<TextBlock x:Name="validationTextBox"
Grid.Row="1"
Grid.ColumnSpan="2"
Text="{Binding ElementName=_this, Path=ValidationMessage}"
TextAlignment="Center"
Background="Green">
<TextBlock.Style>
<Style>
<Style.Triggers>
<DataTrigger Value="False" Binding="{Binding ElementName=_this, Path=ValidationStatus}">
<Setter Property="Panel.Background" Value="Red"/>
<Setter Property="TextBox.Text" Value="Outer checkbox is not checked"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
Style Setters do not override local attribute settings. Therefore the data trigger's values are being ignored because you have specified the Text and Background properties on the TextBlock. To fix the problem set the default values of these properties in the style as shown in the following code:
<TextBlock x:Name="validationTextBox"
Grid.Row="1"
Grid.ColumnSpan="2"
TextAlignment="Center">
<TextBlock.Style>
<Style>
<Setter Property="TextBox.Text" Value="{Binding ElementName=_this, Path=ValidationMessage}"/>
<Setter Property="TextBox.Background" Value="Green"/>
<Style.Triggers>
<DataTrigger Value="False" Binding="{Binding ElementName=_this, Path=ValidationStatus}">
<Setter Property="TextBox.Background" Value="Red"/>
<Setter Property="TextBox.Text" Value="Outer checkbox is not checked"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>

Resources