Change expander background on mouse hover - wpf

I would like to change the expanders background color to a lighter variant on mouse hover. So I figured I use a trigger and a converter to convert the background color to a lighter variant on mouse over. I started simple and only implement the trigger. That works:
<StackPanel>
<StackPanel.Resources>
<Style TargetType="{x:Type Expander}">
<Style.Triggers>
<Trigger Property="Control.IsMouseOver" Value="True">
<Setter Property="Background" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
</StackPanel.Resources>
<Expander Header="Header">
<StackPanel>
<TextBox Background="Transparent">Content</TextBox>
</StackPanel>
</Expander>
</StackPanel>
So I can achieve almost what I want. But I want to be able to set the color on the expander like this:
<Expander Header="Header" Background="Yellow">
The moment I add that the color switching stops working and the expander is always yellow. Why is that happening and how can I achieve my goal?
Edit: in my final application I will have an itemscontrol with multiple expanders whose background color is databound to my view model, so I think I cannot set the color in the style.
<ItemsControl ItemsSource="{Binding TestStepDescriptions}">
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type localVMsTestEngines:AutomaticTestStepDescription}">
<Expander Background="{Binding StepStatus, Converter={StaticResource StepStatusToColorConverter}}">
regards,
Jef

You cannot set that color in the Expander directly if you use a Trigger.
Instead you have to do it like this:
<ItemsControl ItemsSource="{Binding TestStepDescriptions}">
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type localVMsTestEngines:AutomaticTestStepDescription}">
<Expander >
<Expander.Style>
<Style TargetType="{x:Type Expander}">
<Setter Property="Background" Value="{Binding StepStatus, Converter={StaticResource StepStatusToColorConverter}}"/>
<Style.Triggers>
<Trigger Property="Control.IsMouseOver" Value="True">
<Setter Property="Background" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
</Expander.Style>
</Expander>
Usage
<Expander Header="Header">

Related

XAML custom text in TextBlock

Good afternoon,
I´m binding a list of doubles (Latlng) to an ItemsControl and in a TextBlock I want to make a custom text when the list binded has a count of 0. With the code I have the TextBlock is empty when the ItemsSource of the ItemsControl is that list.
What am I doing wrong?
Btw the list Latlng is a property of a class.
<ItemsControl Name="icLatLng" ItemsSource="{Binding Latlng}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock FontFamily="Arial" FontSize="14">
<TextBlock.Style>
<Style>
<Setter Property="TextBlock.Text" Value="{Binding}"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=ItemsControl}, Path=Items.Count}" Value="0">
<Setter Property="TextBlock.Text" Value="—"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Thanks in advance.
Welcome to SO.
ItemsControl.ItemTemplate is the template that gets applied to each element in the Items list the control is bound to. If there are no items to begin with, then it won't be created, so anything you do in it won't be seen.
I suspect what you're really trying to do is replace the look of the entire control when the list is empty. If so, you can do that by applying a new template to the ItemsControl itself using a DataTrigger on the HasItems property:
<ItemsControl Name="icLatLng" ItemsSource="{Binding Latlng}">
<ItemsControl.Style>
<Style TargetType="{x:Type ItemsControl}" BasedOn="{StaticResource {x:Type ItemsControl}}">
<Style.Triggers>
<DataTrigger Binding="{Binding HasItems, RelativeSource={RelativeSource Self}}" Value="False">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ItemsControl}">
<TextBlock Text="-" />
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ItemsControl.Style>
</ItemsControl>

Make background color lighter dynamically

I have a stackpanel with a wrappanel.
When the user hovers over the wrappanel I want the background to be a bit lighter than the current background, so it is clear for the user that he can click it.
The background is bound by my viewmodel and can change.
I use a Converter to convert an enum to a certain color.
<StackPanel x:Name="UserCallAlarmPanel" >
<StackPanel.Resources>
<Style x:Key="AlarmStyle" TargetType="{x:Type WrapPanel}">
<Setter Property="Background" Value="Transparent"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, ElementName=AlarmPanel}" Value="True" >
<Setter Property="Background" Value="{Binding CallStatus, Converter={StaticResource CallStatusBackgroundConverter}}"/>
<Setter Property="Opacity" Value="20"/>
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Resources>
<WrapPanel Name="AlarmPanel" Height="25" MouseLeftButtonDown="AlarmPanel_MouseLeftButtonDown" Style="{StaticResource AlarmStyle}">
<Viewbox>
<ContentControl Content="{DynamicResource alarm_icon}"/>
</Viewbox
</WrapPanel>
</StackPanel>
I tried to change to opacity but that doesn't work.
The valid values for Opacity are between 0 (fully transparent) and 1 (fully opaque). If you want 20% opacity, you need to use 0.2 for the value.

How to change TreeViewItem background color according to property of bound data?

I have a TreeView where the data is bound to generic derived wrapper classes over my data hierarchy.
My bound wrapper classes include added fields like "IsHilighted" and "IsExpanded".
I would like to change the background of any TreeViewItem according to its bound data property "IsHiglighted". I would like to set the color of Hilighted item to the same (or lighter) color as the default Selected item background color.
Ideally, I would like to not modify existing XAML... I mean being able to eventually add the behavior through code.
UPDATE
I have found a partial solution: I had to add triggers as defined below. Code included below.
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="{Binding Path=IsExpanded}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsHilighted}" Value="true">
<Setter Property="Background" Value="SlateBlue"></Setter>
<Setter Property="Opacity" Value="160"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
Still not resolved: How could I bind the color of Hilighted item (see partial solution above) to the "Selected" TreeViewItem background color, i.e. replace "SlateBlue" on partial solution to binding to existing selected item style background color ?
Original TreeView XAML code:
<TreeView Name="TreeViewSelectScopeStudy" MinHeight="24" Margin="7" ItemsSource="{Binding Path=TvItemRootPssTreeViewRoot.ChildsView}" Height="Auto"
VerticalAlignment="Stretch"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling">
<TreeView.Resources>
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="{Binding Path=IsExpanded}"/>
</Style>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Red" />
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Green" />
<HierarchicalDataTemplate DataType="{x:Type scopeSelection:WrapperSimulatedInfoStudy}" ItemsSource="{Binding Path=Childs}">
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding Path=IsSelected}"></CheckBox>
<TextBlock Text="{Binding Path=TvItemName}" Margin="5,0,0,0"></TextBlock>
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type scopeSelection:WrapperSimulatedInfoSimulation}">
<StackPanel Orientation="Horizontal" ToolTip="{Binding Path=Item.InvalidityReason}">
<StackPanel.Style>
<Style TargetType="{x:Type StackPanel}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Item.IsValid}" Value="false">
<Setter Property="Opacity" Value="160"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<CheckBox IsChecked="{Binding Path=IsSelected}" IsEnabled="{Binding Path=Item.IsValid}" ToolTip="{Binding Path=Item.InvalidityReason}"></CheckBox>
<CheckBox IsChecked="{Binding Path=IsHilighted}"></CheckBox>
<TextBlock Text="{Binding Path=TvItemName}" Margin="5,0,0,0" ToolTip="{Binding Path=Item.InvalidityReason}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Item.IsValid}" Value="false">
<Setter Property="Background" Value="LightPink"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
You could define one more property called IsItemSelected and bind it to TreeViewItems IsSelected property (similar to how you have done for IsExpanded).
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="{Binding Path=IsExpanded}"/>
<Setter Property="IsSelected" Value="{Binding Path=IsItemSelected}"/>
</Style>
Then you could define a DataTrigger for the IsItemSelected property and set the background color.
<DataTrigger Binding="{Binding Path=IsItemSelected}" Value="true">
<Setter Property="Background" Value="Blue"></Setter>
</DataTrigger>

WPF Combobox Validation.ErrorTemplate error

I have a combobox that i need to edit its error template to show a red border when there is a validation error.
I am using the following style
<Style TargetType="{x:Type ComboBox}" >
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel>
<Border BorderBrush="Red" BorderThickness="3">
<AdornedElementPlaceholder />
</Border>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="FontFamily" Value="Segoe UI" />
<Setter Property="FontSize" Value="12" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
The border never shows up when validation errors occur. Any tips what is going wrong?
The Style you posted works. You should check your binding, did you add ValidatesOnDataErrors=True and ValidatesOnExceptions=True to the binding of SelectedValue?
enter code heretry without the dock panel, that is uneuseful since it wraps jus one element. However, sicnecerely I don't wnow if it makes sense to wrap a textbox with a border, since it has already a border! You should try to change directly the colour of its border. You could try to use again the panel but then put the border around the panel ie:
Border BorderBrush="Red" BorderThickness="3"
DockPanel
AdornedElement
This makes more sense because the wrap panel has not its own border.
Use This.
<Style x:Key="textBoxStyle" TargetType="{x:Type telerik:RadMaskedTextBox}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
<Setter Property="Control.BorderBrush" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
I don't like any of the responses here. Simply put, how do you change the border color for the error template for a ComboBox using Blend or not? It shouldn't be acceptable to draw another border around the existing border of the ComboBox. I've figured out how to creat a ControlTemplate in Blend but not a Validation Template.
I've come close with trying to make it appear like I've changed the actual border color, but that's not what I actually want. Suggestions? To complicate it a bit, I'd like to display a red asterisk outside of the right border of the control.
The following code is a close attempt, but it is actually drawing a border inside the ComboBox and if you look close, you can see that the border is 2 pixels wide when combined with the ComboBox border:
<DockPanel Name="myDockPanel">
<AdornedElementPlaceholder>
<Border BorderBrush="Blue" BorderThickness="1" CornerRadius="2" />
</AdornedElementPlaceholder>
<TextBlock Text="*" FontWeight="Bold" FontSize="14" Foreground="Red" DockPanel.Dock="Left" ToolTip="{Binding .CurrentItem}" />
</DockPanel>
I searched around some more and came up with a solution based on another article here: WPF - How to apply style to AdornedElementPlaceholder's AdornedElement?
<!-- This works -->
<ComboBox Name="comboBox1" Style="{StaticResource NewComboBoxStyle}" Validation.ErrorTemplate="{StaticResource comboBoxValidationTemplate}" />
<SolidColorBrush x:Key="MainBorderBrush">#FF91B3FF</SolidColorBrush>
<Style x:Key="NewComboBoxStyle" TargetType="{x:Type ComboBox}" BasedOn="{StaticResource myErrorTemplate}">
<Setter Property="BorderBrush" Value="{DynamicResource MainBorderBrush}" />
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="BorderBrush" Value="Blue" />
</Trigger>
</Style.Triggers>
</Style>
<!-- Sets ToolTip when Validation.HasError is True. -->
<Style TargetType="Control" x:Key="myErrorTemplate">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={x:Static RelativeSource.Self},
Path=(Validation.Errors).CurrentItem.ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
<ControlTemplate x:Key="comboBoxValidationTemplate">
<DockPanel Name="myDockPanel">
<AdornedElementPlaceholder/>
<TextBlock Text="*" FontWeight="Bold" FontSize="14" Foreground="Red" DockPanel.Dock="Left" ToolTip="{Binding .CurrentItem}" />
</DockPanel>
</ControlTemplate>

HorizontalContentAlignment of SelectedItem not stretching perfectly

I made a custom styled list in WPF:
<DataTemplate x:Key="SelectedTemplate">
<StackPanel Background="#FF4E4E4E" HorizontalAlignment="Stretch">
<TextBlock Text="{Binding Path=Title}" Foreground="#FFD80000" />
</StackPanel>
</DataTemplate>
<Style TargetType="{x:Type ListBoxItem}" x:Key="ContainerStyle">
<Setter Property="ContentTemplate"
Value="{StaticResource ItemTemplate}" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="ContentTemplate"
Value="{StaticResource SelectedTemplate}" />
</Trigger>
</Style.Triggers>
</Style>
...
<ListBox
Name="lbSongs"
DockPanel.Dock="Left"
ItemsSource="{Binding Path=SongDirectory}"
SelectedItem="{Binding Path=Song, Mode=TwoWay}"
Visibility="{Binding Path=ListVisibility}"
ItemContainerStyle="{StaticResource ContainerStyle}"
HorizontalContentAlignment="Stretch"
Width="180px" Background="#FF333333" />
I tried to make a custom style for the selected item. To make the selection bar stretch to the width of the ListBox, I set the ItemContainerStyle's HorizontalContentAlignment property to "Stretch". The problem is that it does not stretch fully, a tiny bar on the left still remains and the original (blue) selection bar is still visible there. See the screenshot:
How can I make it to stretch to full size? Or how can I style the original selection bar?
Thanks in advance.
Just set the Padding for the ListBoxItem to zero. That blue bar should disappear.
<Style TargetType="{x:Type ListBoxItem}" x:Key="ContainerStyle">
<Setter Property="Padding" Value="0"/>
...
</Style>
Another option is just to re-write the ControlTemplate for the ListBoxItem so that you'll have better control on how it looks like. But yeah, this may not be necessary in your case.

Resources