WPF Removing custom ListViewItem mouseover blue rectangle - wpf

I'm using this code for a custom user control of type ListViewItem :
<UserControl.Resources>
<Style x:Key="Properties" TargetType="local:CustomListViewItem">
<Setter Property="ButtonImageSource" Value="{Binding ButtonImageSource, Mode=TwoWay}"/>
<Setter Property="ButtonText" Value="{Binding ButtonText, Mode=TwoWay}"/>
</Style>
<Style x:Key="ListViewItemStyle" TargetType="{x:Type ListViewItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border
x:Name="Bd"
Width="{Binding RelativeSource={RelativeSource AncestorType=ListView}, Path=ActualWidth}"
Height="50"
Padding="{TemplateBinding Padding}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Cursor="Hand"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
<ContentPresenter
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Border>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True" />
</MultiTrigger.Conditions>
<MultiTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetName="Bd"
Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
From="{StaticResource DarkGrey34}"
To="{StaticResource DarkGrey80}"
Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</MultiTrigger.EnterActions>
<MultiTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetName="Bd"
Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
From="{StaticResource DarkGrey80}"
To="{StaticResource DarkGrey34}"
Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</MultiTrigger.ExitActions>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<ListViewItem
Padding="0"
HorizontalAlignment="Left"
Style="{StaticResource ListViewItemStyle}"
>
<StackPanel x:Name="Panel" HorizontalAlignment="Left" Orientation="Horizontal">
<Image
Margin="4"
Source="{Binding ButtonImageSource}"
Stretch="Uniform"
Style="{StaticResource ImageShaddow}" />
<TextBlock
Margin="15,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Style="{StaticResource TextBlockStyle}"
Text="{Binding ButtonText}" />
</StackPanel>
</ListViewItem>
and implementation of this CustomListViewItem is:
<ListView
x:Name="MenuButtonsList"
Background="Transparent"
BorderThickness="0"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<!-- Create file button -->
<comp:ListViewItem
x:Name="BtnCreateFile"
PreviewMouseLeftButtonUp="BtnCreateFile_PreviewMouseLeftButtonUp"
ButtonImageSource="{StaticResource ArticleWhite}"
ButtonText="Create File"
/>
<!-- Open File button -->
<comp:ListViewItem
x:Name="BtnOpenFile"
PreviewMouseLeftButtonUp="BtnOpenFile_PreviewMouseLeftButtonUp"
ButtonImageSource="{StaticResource OpenFile}"
ButtonText="Open File"
/>
<!-- Settings button -->
<comp:ListViewItem
x:Name="BtnSettings"
PreviewMouseLeftButtonUp="BtnSettings_PreviewMouseLeftButtonUp"
ButtonImageSource="{StaticResource SettingsWhite}"
ButtonText="Settings"
/>
</ListView>
Even if the style is customized, the blue rectangle on mouse over it appears.
What I'm missing?

You're going about this all wrong. Creating custom user controls for things like ListViewItem is the old-school WinForms way of doing things, for WPF you instead apply custom templates. Start by using regular ListViewItems in your ListView (which I've simplified here for illustration purposes):
<ListView
x:Name="MenuButtonsList"
Background="Transparent"
BorderThickness="0"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<!-- Create file button -->
<ListViewItem />
<!-- Open File button -->
<ListViewItem />
<!-- Settings button -->
<ListViewItem />
</ListView>
Now template out ListViewItem. You can do this by placing the cursor over any instance and then in the Properties panel clicking to the right of Common -> Template and selecting "Convert to new resource". This will expand out the Control Template into something you can work with:
<Window.Resources>
<SolidColorBrush x:Key="Item.MouseOver.Background" Color="#1F26A0DA"/>
<SolidColorBrush x:Key="Item.MouseOver.Border" Color="#a826A0Da"/>
<SolidColorBrush x:Key="Item.SelectedActive.Background" Color="#3D26A0DA"/>
<SolidColorBrush x:Key="Item.SelectedActive.Border" Color="#FF26A0DA"/>
<SolidColorBrush x:Key="Item.SelectedInactive.Background" Color="#3DDADADA"/>
<SolidColorBrush x:Key="Item.SelectedInactive.Border" Color="#FFDADADA"/>
<ControlTemplate x:Key="ListViewItemTemplate1" TargetType="{x:Type ListBoxItem}">
<Border x:Name="Bd" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.MouseOver.Background}"/>
<Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.MouseOver.Border}"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Selector.IsSelectionActive" Value="False"/>
<Condition Property="IsSelected" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.SelectedInactive.Background}"/>
<Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.SelectedInactive.Border}"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Selector.IsSelectionActive" Value="True"/>
<Condition Property="IsSelected" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.SelectedActive.Background}"/>
<Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.SelectedActive.Border}"/>
</MultiTrigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="TextElement.Foreground" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Window.Resources>
The field you're trying to nuke is this one, just change it to "Transparent":
<SolidColorBrush x:Key="Item.MouseOver.Border" Color="#a826A0Da"/>
Expanding out the template manually applies the template like so:
<!-- Create file button -->
<ListViewItem Template="{DynamicResource ListViewItemTemplate1}" />
If you want to set this automatically then simply set the style for TargetType="ListViewItem", either in Window.Resources (which will set it to all ListViewItems in the window) or ListView.Resources (which will set it just to the ones in that control instance):
<Style TargetType="ListViewItem">
<Setter Property="Template" Value="{StaticResource ListViewItemTemplate1}" />
</Style>
Upon reading this you might be thinking that it isn't applicable on account of the fact that you also need to override the layout of ListViewItem itself. In that case, you still don't need to use a custom ListViewItem, you instead use a DataTemplate. ControlTemplate is used for the top-most presentation of the ListViewItem, whereas DataTemplate is used to specify how the data within the item is presented. It's a subtle distinction, but core to how this part of WPF has been architected.

Related

How do you change Background for a Button MouseOver in WPF?

I have a button on my page with this XAML:
<Button Content="Button" HorizontalAlignment="Left" VerticalAlignment="Bottom"
Width="50" Height="50" HorizontalContentAlignment="Left"
BorderBrush="{x:Null}" Foreground="{x:Null}" Margin="50,0,0,0">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Background" Value="Green"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
But when I put mouse over my button, button's background changes to default windows gray background.What's The Problem?
This is the button picture before and after mouseover:
Before:
After:
To remove the default MouseOver behaviour on the Button you will need to modify the ControlTemplate. Changing your Style definition to the following should do the trick:
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="Green"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}" BorderBrush="Black" BorderThickness="1">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
EDIT: It's a few years late, but you are actually able to set the border brush inside of the border that is in there. Idk if that was pointed out but it doesn't seem like it was...
All of the answers so far involve completely replacing the default button behavior with something else. However, IMHO it is useful and important to understand that it's possible to change just the part you care about, by editing the existing, default template for a XAML element.
In the case of dealing with the hover effect on a WPF button, the change in appearance in a WPF Button element is caused by a Trigger in the default style for the Button, which is based on the IsMouseOver property and sets the Background and BorderBrush properties of the top-level Border element in the control template. The Button element's background is underneath the Border element's background, so changing the Button.Background property doesn't prevent the hover effect from being seen.
With some effort, you could override this behavior with your own setter, but because the element you need to affect is in the template and not directly accessible in your own XAML, that approach would be difficult and IMHO overly complex.
Another option would be to make use the graphic as the Content for the Button rather than the Background. If you need additional content over the graphic, you can combine them with a Grid as the top-level object in the content.
However, if you literally just want to disable the hover effect entirely (rather than just hiding it), you can use the Visual Studio XAML Designer:
While editing your XAML, select the "Design" tab.
In the "Design" tab, find the button for which you want to disable the effect.
Right-click that button, and choose "Edit Template/Edit a Copy...". Select in the prompt you get where you want the new template resource to be placed. This will appear to do nothing, but in fact the Designer will have added new resources where you told it, and changed your button element to reference the style that uses those resources as the button template.
Now, you can go edit that style. The easiest thing is to delete or comment-out (e.g. Ctrl+E, C) the <Trigger Property="IsMouseOver" Value="true">...</Trigger> element. Of course, you can make any change to the template you want at that point.
When you're done, the button style will look something like this:
<p:Style x:Key="FocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="2" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</p:Style>
<SolidColorBrush x:Key="Button.Static.Background" Color="#FFDDDDDD"/>
<SolidColorBrush x:Key="Button.Static.Border" Color="#FF707070"/>
<SolidColorBrush x:Key="Button.MouseOver.Background" Color="#FFBEE6FD"/>
<SolidColorBrush x:Key="Button.MouseOver.Border" Color="#FF3C7FB1"/>
<SolidColorBrush x:Key="Button.Pressed.Background" Color="#FFC4E5F6"/>
<SolidColorBrush x:Key="Button.Pressed.Border" Color="#FF2C628B"/>
<SolidColorBrush x:Key="Button.Disabled.Background" Color="#FFF4F4F4"/>
<SolidColorBrush x:Key="Button.Disabled.Border" Color="#FFADB2B5"/>
<SolidColorBrush x:Key="Button.Disabled.Foreground" Color="#FF838383"/>
<p:Style x:Key="ButtonStyle1" TargetType="{x:Type Button}">
<Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/>
<Setter Property="Background" Value="{StaticResource Button.Static.Background}"/>
<Setter Property="BorderBrush" Value="{StaticResource Button.Static.Border}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="true">
<ContentPresenter x:Name="contentPresenter" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsDefaulted" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
</Trigger>
<!--<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background" TargetName="border" Value="{StaticResource Button.MouseOver.Background}"/>
<Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.MouseOver.Border}"/>
</Trigger>-->
<Trigger Property="IsPressed" Value="true">
<Setter Property="Background" TargetName="border" Value="{StaticResource Button.Pressed.Background}"/>
<Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.Pressed.Border}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" TargetName="border" Value="{StaticResource Button.Disabled.Background}"/>
<Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.Disabled.Border}"/>
<Setter Property="TextElement.Foreground" TargetName="contentPresenter" Value="{StaticResource Button.Disabled.Foreground}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</p:Style>
(Note: you can omit the p: XML namespace qualifications in the actual codeā€¦I provide them here only because the Stack Overflow XML code formatter gets confused by <Style/> elements that don't have a fully-qualified name with XML namespace.)
If you want to apply the same style to other buttons, you can just right-click them and choose "Edit Template/Apply Resource" and select the style you just added for the first button. You can even make that style the default style for all buttons, using the normal techniques for applying a default style to elements in XAML.
This worked well for me.
Button Style
<Style x:Key="TransparentStyle" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border>
<Border.Style>
<Style TargetType="{x:Type Border}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="DarkGoldenrod"/>
</Trigger>
</Style.Triggers>
</Style>
</Border.Style>
<Grid Background="Transparent">
<ContentPresenter></ContentPresenter>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Button
<Button Style="{StaticResource TransparentStyle}" VerticalAlignment="Top" HorizontalAlignment="Right" Width="25" Height="25"
Command="{Binding CloseWindow}">
<Button.Content >
<Grid Margin="0 0 0 0">
<Path Data="M0,7 L10,17 M0,17 L10,7" Stroke="Blue" StrokeThickness="2" HorizontalAlignment="Center" Stretch="None" />
</Grid>
</Button.Content>
</Button>
Notes
The button displays a little blue cross, much like the one used to close a window.
By setting the background of the grid to "Transparent", it adds a hittest, which means that if the mouse is anywhere over the button, then it will work. Omit this tag, and the button will only light up if the mouse is over one of the vector lines in the icon (this is not very usable).
Just want to share my button style from my ResourceDictionary that i've been using.
You can freely change the onHover background at the style triggers.
"ColorAnimation To = *your desired BG(i.e #FFCEF7A0)". The button BG will also automatically revert to its original BG after the mouseOver state.You can even set how fast the transition.
Resource Dictionary
<Style x:Key="Flat_Button" TargetType="{x:Type Button}">
<Setter Property="Width" Value="100"/>
<Setter Property="Height" Value="50"/>
<Setter Property="Margin" Value="2"/>
<Setter Property="FontFamily" Value="Arial Narrow"/>
<Setter Property="FontSize" Value="12px"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Foreground">
<Setter.Value>
<SolidColorBrush Opacity="1" Color="White"/>
</Setter.Value>
</Setter>
<Setter Property="Background" >
<Setter.Value>
<SolidColorBrush Opacity="1" Color="#28C2FF" />
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="border"
SnapsToDevicePixels="True"
BorderThickness="1"
Padding="4,2"
BorderBrush="Gray"
CornerRadius="3"
Background="{TemplateBinding Background}">
<Grid>
<ContentPresenter
Margin="2"
HorizontalAlignment="Center"
VerticalAlignment="Center"
RecognizesAccessKey="True" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation To="#D2F898"
Storyboard.TargetProperty="(Control.Background).(SolidColorBrush.Color)"
FillBehavior="HoldEnd" Duration="0:0:0.25" AutoReverse="False" RepeatBehavior="1x"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetProperty="(Control.Background).(SolidColorBrush.Color)"
FillBehavior="HoldEnd" Duration="0:0:0.25" AutoReverse="False" RepeatBehavior="1x"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
all you have to do is call the style.
Example Implementation
<Button Style="{StaticResource Flat_Button}" Height="Auto"Width="Auto">
<StackPanel>
<TextBlock Text="SAVE" FontFamily="Arial" FontSize="10.667"/>
</StackPanel>
</Button>
A slight more difficult answer that uses ControlTemplate and has an animation effect
(adapted from https://learn.microsoft.com/en-us/dotnet/framework/wpf/controls/customizing-the-appearance-of-an-existing-control)
In your resource dictionary define a control template for your button like this one:
<ControlTemplate TargetType="Button" x:Key="testButtonTemplate2">
<Border Name="RootElement">
<Border.Background>
<SolidColorBrush x:Name="BorderBrush" Color="Black"/>
</Border.Background>
<Grid Margin="4" >
<Grid.Background>
<SolidColorBrush x:Name="ButtonBackground" Color="Aquamarine"/>
</Grid.Background>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="4,5,4,4"/>
</Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Storyboard.TargetName="ButtonBackground" Storyboard.TargetProperty="Color" To="Red"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimation Storyboard.TargetName="ButtonBackground" Storyboard.TargetProperty="Color" To="Red"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Border>
</ControlTemplate>
in your XAML you can use the template above for your button as below:
Define your button
<Button Template="{StaticResource testButtonTemplate2}"
HorizontalAlignment="Center" VerticalAlignment="Center"
Foreground="White">My button</Button>
Hope it helps
For change button style
1st: define resource styles
<Window.Resources>
<Style x:Key="OvergroundIn" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Background="#FF16832F">
<ContentPresenter TextBlock.Foreground="White" TextBlock.TextAlignment="Center" Margin="0,8,0,0" ></ContentPresenter>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Background="#FF06731F">
<ContentPresenter TextBlock.Foreground="White" TextBlock.TextAlignment="Center" Margin="0,8,0,0" ></ContentPresenter>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="OvergroundOut" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Background="#FFF35E5E">
<ContentPresenter TextBlock.Foreground="White" TextBlock.TextAlignment="Center" Margin="0,8,0,0" ></ContentPresenter>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Background="#FFE34E4E">
<ContentPresenter TextBlock.Foreground="White" TextBlock.TextAlignment="Center" Margin="0,8,0,0" ></ContentPresenter>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
2nd define button code
<Border Grid.Column="2" BorderBrush="LightGray" BorderThickness="2" CornerRadius="3" Margin="2,2,2,2" >
<Button Name="btnFichar" BorderThickness="0" Click="BtnFichar_Click">
<Button.Content>
<Grid>
<TextBlock Margin="0,7,0,7" TextAlignment="Center">Fichar</TextBlock>
</Grid>
</Button.Content>
</Button>
</Border>
3th code behind
public void ShowStatus()
{
switch (((MainDto)this.DataContext).State)
{
case State.IN:
this.btnFichar.BorderBrush = new SolidColorBrush(Color.FromRgb(243, 94, 94));
this.btnFichar.Style = Resources["OvergroundIn"] as Style;
this.btnFichar.Content = "Fichar Salida";
break;
case State.OUT:
this.btnFichar.BorderBrush = new SolidColorBrush(Color.FromRgb(76, 106, 83));
this.btnFichar.Style = Resources["OvergroundOut"] as Style;
this.btnFichar.Content = "Fichar Entrada";
break;
}
}

Remove Extra Space around Listbox

I have some extra space around my Listbox. It's 1px wide, but I don't know where it comes from...
I set the padding, margin and BorderThickness of both, the ListBox and the ListboxItem to 0.
This is the XAML:
<!-- NOTEBOX LISTBOX -->
<!-- The Datatemplate for the Notebox - ListboxItem -->
<DataTemplate x:Key="NoteListboxItemTemplate" DataType="ListBoxItem">
<Border Style="{DynamicResource OuterNoteBoxBorder}">
<Border Style="{DynamicResource SecondOuterNoteBoxBorder}">
<StackPanel>
<TextBlock Grid.Column="0" Foreground="#225588" Text="{Binding Title}" Style="{DynamicResource PlayListListBoxTitleLabel}" TextTrimming="CharacterEllipsis" TextWrapping="NoWrap" ></TextBlock>
<ContentPresenter Content="{Binding NoteView}"></ContentPresenter>
<TextBlock Grid.Column="1" Foreground="Black" Text="{local:CultureAwareBinding CreationDate, StringFormat={}{0:F}}" Style="{DynamicResource PlayListListBoxTitleLabel}"></TextBlock>
</StackPanel>
</Border>
</Border>
</DataTemplate>
<!-- The Itemtemplate for the Notebox - ListboxItem -->
<Style x:Key="NoteboxListItemTemplate" TargetType="{x:Type ListBoxItem}">
<Setter Property="Margin" Value="0" />
<Setter Property="Padding" Value="0" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="Background" Value="White" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
<!--<Setter Property="Background" TargetName="Bd" Value="#66000000"/>
<Setter Property="BorderBrush" Value="#000000" />-->
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="true"/>
<Condition Property="Selector.IsSelectionActive" Value="false"/>
</MultiTrigger.Conditions>
<!--<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>-->
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
</MultiTrigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="#88000000"/>
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent"/>
</Style.Resources>
</Style>
<!-- The Border-Template for our Notebox - ListboxItem -->
<Style x:Key="NoteboxListItemBorderTemplate" TargetType="{x:Type Border}">
<Setter Property="Background" Value="#CCFFFFFF" />
<Setter Property="Margin" Value="0" />
<Setter Property="Padding" Value="0" />
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="#88000000"/>
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="#44000000"/>
</Style.Resources>
</Style>
<!-- Notebox - Listbox Template -->
<Style x:Key="NoteboxListboxTemplate" TargetType="{x:Type ListBox}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Padding" Value="0" />
<Setter Property="Margin" Value="0" />
</Style>
<ListBox Grid.Column="1"
Grid.Row="0"
Background="Black"
MouseDoubleClick="ListBox_MouseDoubleClick"
HorizontalContentAlignment="Stretch"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ItemContainerStyle="{DynamicResource NoteboxListItemTemplate}"
VirtualizingStackPanel.VirtualizationMode="Recycling"
VirtualizingStackPanel.IsVirtualizing="True"
ItemsSource="{Binding Notes, Mode=TwoWay}"
ItemTemplate="{DynamicResource NoteListboxItemTemplate}"
SelectedItem="{Binding SelectedNote}"
Style="{DynamicResource NoteboxListboxTemplate}">
</ListBox>
What am I missing?
This is the default control template for ListBox:
<ControlTemplate x:Key="ListBoxControlTemplate1" TargetType="{x:Type ListBox}">
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="1" SnapsToDevicePixels="True">
<ScrollViewer Focusable="False" Padding="{TemplateBinding Padding}">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</ScrollViewer>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
</Trigger>
<Trigger Property="IsGrouping" Value="True">
<Setter Property="ScrollViewer.CanContentScroll" Value="False"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
Notice the Padding="1" on Border named Bd. Since this is harcoded and not template bound, you can either retemplate the ListBox and set the padding to 0, or since Padding on the ScollViewer has a TemplateBinding to the Padding of the ListBox, you can set the Padding on your ListBox to -1 to offset the padding on the border.
The control template of a ListBox looks like this:
<ControlTemplate TargetType="{x:Type ListBox}">
<Border Name="Bd"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="true"
Padding="1"> <!-- This might be the problem -->
<!-- ... -->
Try to put Padding="-1" in the ListBox.

Displaying Errors, Having Controls After to Move Downwards

So I am trying to have a message displayed when the input is invalid, suppose I want something other than a ToolTip, something that stays until the error is corrected. I tried having an ErrorTemplate
<Style TargetType="{x:Type TextBox}">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<StackPanel>
<Border BorderBrush="Red" BorderThickness="1">
<AdornedElementPlaceholder x:Name="adornedErrorElement" />
</Border>
<Label Background="Red" Foreground="White" FontSize="9" Content="{Binding ElementName=adornedErrorElement, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<StackPanel Margin="20">
<TextBlock Text="Name" />
<TextBox Text="{Binding Name}" />
<TextBlock Text="Email" />
<TextBox Text="{Binding Path=Email, ValidatesOnDataErrors=True}" />
<Button Content="Submit" />
</StackPanel>
I get
Where the label overlays elements after it. How can I have it such that it works just like another element in the stackpanel?
UPDATE: Using The VSM
Now, I want to go 1 step further and animate the error label up and down. I am considering VSM following #robertos answer. I tried implementing in in Blend. A few problems I faced. I tried
<ControlTemplate TargetType="{x:Type TextBox}">
<StackPanel Orientation="Vertical">
<Microsoft_Windows_Themes:ListBoxChrome ...>
<VisualStateManager.VisualStateGroups>
...
</VisualStateManager.VisualStateGroups>
<ScrollViewer ... />
</Microsoft_Windows_Themes:ListBoxChrome>
<Label Content="Error Here" />
</StackPanel>
</ControlTemplate>
Then I lost access to VisualStates in Blend. Then I tried
<Microsoft_Windows_Themes:ListBoxChrome>
<StackPanel>
<ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Margin="2,0,-2,0"/>
<TextBlock x:Name="textBlock" Background="Red" Foreground="White" FontWeight="Bold" Text="Hello" Visibility="Collapsed" />
</StackPanel>
</Microsoft_Windows_Themes:ListBoxChrome>
Not ideal as the StackPanel is within the border. Also my attempts at animation looks just weird
http://screenr.com/byk
http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,115,0' width='560' height='345'>http://screenr.com/Content/assets/screenr_1116090935.swf' >http://screenr.com/Content/assets/screenr_1116090935.swf' flashvars='i=130553' allowFullScreen='true' width='560' height='345' pluginspage='http://www.macromedia.com/go/getflashplayer' >
1st I must make the label hidden instead of collapsed the animate just the opacity. I want the label to appear like its coming out from the textbox
The element would have to be a part of the same StackPanel in the VisualTree which is not the case with the Validation.ErrorTemplate as you noticed. One way to do this would be to retemplate the TextBox and make place for a Collapsed error Label which will turn visible on Validation.HasError. You'll need to add a reference to PresentationFramework.Aero.
xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
Xaml
<LinearGradientBrush x:Key="TextBoxBorder" EndPoint="0,20" StartPoint="0,0" MappingMode="Absolute">
<GradientStop Color="#ABADB3" Offset="0.05"/>
<GradientStop Color="#E2E3EA" Offset="0.07"/>
<GradientStop Color="#E3E9EF" Offset="1"/>
</LinearGradientBrush>
<Style x:Key="LabelValidationTextBox" BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
<Setter Property="BorderBrush" Value="{StaticResource TextBoxBorder}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="AllowDrop" Value="true"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<StackPanel Orientation="Vertical">
<Microsoft_Windows_Themes:ListBoxChrome x:Name="Bd" SnapsToDevicePixels="true" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" RenderFocused="{TemplateBinding IsKeyboardFocusWithin}" RenderMouseOver="{TemplateBinding IsMouseOver}">
<ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Microsoft_Windows_Themes:ListBoxChrome>
<Label StackPanel.ZIndex="-1" Name="errorLabel" Height="22" Margin="0,-22,0,0" Background="Red" Foreground="White" FontSize="9" Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(Validation.Errors)[0].ErrorContent}" />
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
<Trigger Property="Validation.HasError" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard TargetName="errorLabel" TargetProperty="Margin">
<ThicknessAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetProperty="Margin">
<SplineThicknessKeyFrame KeyTime="0:0:0.0" Value="0,-22,0,0"/>
<SplineThicknessKeyFrame KeyTime="0:0:0.5" Value="0,0,0,0"/>
</ThicknessAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard TargetName="errorLabel" TargetProperty="Margin">
<ThicknessAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetProperty="Margin">
<SplineThicknessKeyFrame KeyTime="0:0:0.0" Value="0,0,0,0"/>
<SplineThicknessKeyFrame KeyTime="0:0:0.5" Value="0,-22,0,0"/>
</ThicknessAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Update
Added Margin animation of the Label. It will "slide out" of the TextBox when Validation.HasError is True and "slide back in" to the TextBox when Validation.HasError is False.
Instead of using ErrorTemplate, you could use the Visual State Manager and customize the Invalid State. By doing that, besides being able to integrate your changes to the actual control (which affects layout), you'll also get the ability to animate state changes very easily as well.
If you need more guidance on Visual States don't hesitate to ask.

The Background of the selected row do not change in ListView Control

I have the following ListView with a ListView.ItemTemplate:
<ListView.ItemTemplate>
<DataTemplate>
<StackPanelName="stackPanel" Orientation="Horizontal">
<TextBoxName="textBoxOrg"
Background="Transparent" BorderThickness="0" TextWrapping="Wrap" Text="{BindingOrgText}"
IsReadOnly="True"/>
<TextBoxName="textBoxNew"
Background="Transparent" BorderThickness="0" TextWrapping="Wrap" Text="{BindingNewText}"
AcceptsReturn="True"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
And the following ListViewItemStyle
<Style TargetType="ListViewItem">
<Setter Property="SnapsToDevicePixels" Value="True" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="LightGoldenrodYellow" />
</Trigger>
</Style.Triggers>
</Style>
I want to change the default 'Blue' background color of the selected item, but when using the above code, it did not change to 'LightGoldenrodYellow' when I select an item.
How should I fix the code to let it work properly?
You need to customize the ControlTemplate of the ListViewItem. Otherwise it overrides(doesnt use) the Background trigger you defined. Here is the default template to customize (I'm using a helpful little tool called stylesnooper to get the templates http://wpfwonderland.wordpress.com/2007/01/02/wpf-tools-stylesnooper/):
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border BorderThickness="{TemplateBinding Border.BorderThickness}" Padding="{TemplateBinding Control.Padding}" BorderBrush="{TemplateBinding Border.BorderBrush}" Background="{TemplateBinding Panel.Background}" Name="Bd" SnapsToDevicePixels="True">
<ContentPresenter Content="{TemplateBinding ContentControl.Content}" ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}" ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}" HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding Control.VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="Selector.IsSelected">
<Setter Property="Panel.Background" TargetName="Bd">
<Setter.Value>
<DynamicResource ResourceKey="{x:Static SystemColors.HighlightBrushKey}" />
</Setter.Value>
</Setter>
<Setter Property="TextElement.Foreground">
<Setter.Value>
<DynamicResource ResourceKey="{x:Static SystemColors.HighlightTextBrushKey}" />
</Setter.Value>
</Setter>
<Trigger.Value>
<s:Boolean>
True</s:Boolean>
</Trigger.Value>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Selector.IsSelected">
<Condition.Value>
<s:Boolean>
True</s:Boolean>
</Condition.Value>
</Condition>
<Condition Property="Selector.IsSelectionActive">
<Condition.Value>
<s:Boolean>
False</s:Boolean>
</Condition.Value>
</Condition>
</MultiTrigger.Conditions>
<Setter Property="Panel.Background" TargetName="Bd">
<Setter.Value>
<DynamicResource ResourceKey="{x:Static SystemColors.ControlBrushKey}" />
</Setter.Value>
</Setter>
<Setter Property="TextElement.Foreground">
<Setter.Value>
<DynamicResource ResourceKey="{x:Static SystemColors.ControlTextBrushKey}" />
</Setter.Value>
</Setter>
</MultiTrigger>
<Trigger Property="UIElement.IsEnabled">
<Setter Property="TextElement.Foreground">
<Setter.Value>
<DynamicResource ResourceKey="{x:Static SystemColors.GrayTextBrushKey}" />
</Setter.Value>
</Setter>
<Trigger.Value>
<s:Boolean>
False</s:Boolean>
</Trigger.Value>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
Dr WPF has a excellent article on ItemsControls called (ItemsControl: A to Z) and read I and L
I finally work out like this:
<Style x:Key="myListboxStyle">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="#CCFFFFFF" />
</Style.Resources>
</Style>
And it works perfect.
Thanks all of you.

Elegantly override style of ComboBox's ToggleButton in WPF

I have a question regarding how to elegantly override an arbitrary element deep inside a control's visual tree. I also have attempted to resolve it in a few different ways, but I've run into several problems with each. Usually when I try three different paths and fail at each one I go downstairs, have a coffee, and ask someone smarter than myself. So here I am.
Specifics:
I want to flatten the style of a combo box so that it will not draw attention to itself. I want it to be similar to Windows.Forms.ComboBox's FlatStyle I want it to look the same on Windows 7 and XP.
Mainly, I want to change the look of a ComboBox's ToggleButton.
I could just use Blend and rip the control template's guts out and manually change them. That doesn't sound very appetizing to me.
I tried using a style to override the ToggleButton's background, but it turns out that the whole ComboBox control is actually a front for a ToggleButton.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ComboBoxExpiriment2.MainWindow"
x:Name="Window"
xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Classic" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="204" Height="103">
<Grid x:Name="LayoutRoot">
<ComboBox HorizontalAlignment="Left" Margin="32,26.723,0,0" Width="120" VerticalAlignment="Top" Height="21.277">
<ComboBox.Style>
<Style>
<Setter Property="ToggleButton.Background" Value="Green" />
</Style>
</ComboBox.Style>
</ComboBox>
</Grid>
So I gave up and ripped it using Blend. I found that it's actually a Style called ComboBoxTransparentButtonStyle with a target type of ToggleButton. The style sets a ControlTemplate that uses a DockPanel that has a "Microsoft_Windows_Themes:ClassicBorderDecorator" type set to the right, and that's what we're actually trying to control. (Are you with me so far?)
Here's the pic:
<Style x:Key="ComboBoxTransparentButtonStyle" TargetType="{x:Type ToggleButton}">
<Setter Property="MinWidth" Value="0"/>
<Setter Property="MinHeight" Value="0"/>
<Setter Property="Width" Value="Auto"/>
<Setter Property="Height" Value="Auto"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="{x:Static Microsoft_Windows_Themes:ClassicBorderDecorator.ClassicBorderBrush}"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<DockPanel SnapsToDevicePixels="true" Background="{TemplateBinding Background}" LastChildFill="false">
<Microsoft_Windows_Themes:ClassicBorderDecorator x:Name="Border" Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" DockPanel.Dock="Right" Background="Green" BorderBrush="{TemplateBinding BorderBrush}" BorderStyle="None" BorderThickness="{TemplateBinding BorderThickness}">
<Path Fill="{TemplateBinding Foreground}" HorizontalAlignment="Center" VerticalAlignment="Center" Data="{StaticResource DownArrowGeometry}"/>
</Microsoft_Windows_Themes:ClassicBorderDecorator>
</DockPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="true">
<Setter Property="BorderStyle" TargetName="Border" Value="AltPressed"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}"/>
</Trigger>
</Style.Triggers>
</Style>
Arg. Isn't WPF a blast?
So I extracted the style ComboBoxTransparentButtonStyle and dropped it into another project's application.resources. Problem is I can't apply that style to a ComboBox because the style I extracted has a targetType of ToggleButton, so the TargeTypes don't match.
tl;dr how would you guys do it?
There isn't an elegant solution for this. The best you can do is override the style for the entire ComboBox so that you can change the style it sets for the ToggleButton.
You can use Blend to get the styles, however that probabliy isn't the easiest way. If you have Blend installed, go to "[Program files or where Blend is installed]\SystemThemes\WPF\areo.normalcolor.xaml".
A Working Solution
Hi, this style satisfies your needs, feel free to edit it as you need:
<SolidColorBrush x:Key="WindowBackgroundBrush" Color="White" />
<SolidColorBrush x:Key="MainColor" Color="DeepSkyBlue"/>
<SolidColorBrush x:Key="MainColorLight" Color="LightSkyBlue"/>
<SolidColorBrush x:Key="MainColorDark" Color="#00A7DF"/>
<SolidColorBrush x:Key="BorderMainBrush" Color="LightGray"/>
<SolidColorBrush x:Key="BorderDarkMainBrush" Color="#C0C0C0"/>
<SolidColorBrush x:Key="BackgroundGrayDark" Color="#FFEFEFEF"/>
<SolidColorBrush x:Key="BackgroundGrayLight" Color="#F5F5F5"/>
<SolidColorBrush x:Key="ForegroundDisabledBrush" Color="DimGray"/>
<SolidColorBrush x:Key="ForegroundBrush" Color="Black"/>
<LinearGradientBrush x:Key="FormBackgroundBrush"
EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFFFFD" Offset="0.31" />
<GradientStop Color="#FFF8F8F8" Offset="1" />
</LinearGradientBrush>
<ControlTemplate x:Key="ComboBoxToggleButton" TargetType="ToggleButton">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver"/>
<VisualState x:Name="Pressed"/>
<VisualState x:Name="Disabled"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="Border" SnapsToDevicePixels="True" Grid.ColumnSpan="2" Background="{DynamicResource BackgroundGrayDark}" BorderBrush="{DynamicResource BorderDarkMainBrush}" BorderThickness="1" />
<Border x:Name="Border2" Grid.Column="0" SnapsToDevicePixels="True" Margin="1" Background="{StaticResource WindowBackgroundBrush}" BorderBrush="{DynamicResource BorderDarkMainBrush}" BorderThickness="0,0,1,0" />
<Path x:Name="Arrow" Grid.Column="1" Data="M 0 0 L 4 4 L 8 0 Z" Fill="DimGray" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="ToggleButton.IsMouseOver" Value="true">
<Setter Property="Background" TargetName="Border" Value="{DynamicResource MainColor}" />
<Setter Property="BorderBrush" TargetName="Border" Value="{DynamicResource MainColor}" />
<Setter Property="BorderBrush" TargetName="Border2" Value="{DynamicResource MainColor}" />
<Setter Property="Fill" TargetName="Arrow" Value="White" />
</Trigger>
<Trigger Property="ToggleButton.IsChecked" Value="true">
<Setter Property="Background" TargetName="Border" Value="{DynamicResource MainColorDark}" />
<Setter Property="BorderBrush" TargetName="Border" Value="{DynamicResource MainColorDark}" />
<Setter Property="BorderBrush" TargetName="Border2" Value="{DynamicResource MainColorDark}" />
<Setter Property="Fill" TargetName="Arrow" Value="White" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" TargetName="Border" Value="{DynamicResource BackgroundGrayLight}" />
<Setter Property="BorderBrush" TargetName="Border" Value="{StaticResource BorderMainBrush}" />
<Setter Property="Foreground" Value="{StaticResource ForegroundDisabledBrush}" />
</Trigger>
<DataTrigger Binding="{Binding IsKeyboardFocusWithin, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=OneWay}" Value="True">
<Setter Property="Background" TargetName="Border" Value="{DynamicResource MainColorLight}" />
<Setter Property="BorderBrush" TargetName="Border" Value="{DynamicResource MainColorLight}" />
<Setter Property="BorderBrush" TargetName="Border2" Value="{DynamicResource MainColorLight}" />
<Setter Property="Fill" TargetName="Arrow" Value="White" />
</DataTrigger >
</ControlTemplate.Triggers>
</ControlTemplate>
<ControlTemplate x:Key="ComboBoxTextBox" TargetType="TextBox">
<Border x:Name="PART_ContentHost" Background="{TemplateBinding Background}" Focusable="False" />
</ControlTemplate>
<Style TargetType="ComboBox">
<Setter Property="Validation.ErrorTemplate" Value="{x:Null}" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="IsEditable" Value="True"/>
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
<Setter Property="ScrollViewer.CanContentScroll" Value="true" />
<Setter Property="Margin" Value="2" />
<Setter Property="MinHeight" Value="20" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBox">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver"/>
<VisualState x:Name="Disabled"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ToggleButton x:Name="ToggleButton" Grid.Column="2" ClickMode="Press" Focusable="false"
IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
Template="{StaticResource ComboBoxToggleButton}"/>
<ContentPresenter Margin="3,3,23,3" Content="{TemplateBinding SelectionBoxItem}"
ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
HorizontalAlignment="Left" IsHitTestVisible="False" x:Name="ContentSite"
VerticalAlignment="Center" />
<TextBox Style="{x:Null}" x:Name="PART_EditableTextBox" Margin="3,3,23,3" Background="Transparent"
Focusable="True" HorizontalAlignment="Left" IsReadOnly="{TemplateBinding IsReadOnly}"
Template="{StaticResource ComboBoxTextBox}" VerticalAlignment="Center" Visibility="Hidden" />
<Popup AllowsTransparency="True" Focusable="False" IsOpen="{TemplateBinding IsDropDownOpen}" x:Name="Popup" Placement="Bottom" PopupAnimation="Fade">
<Grid MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{TemplateBinding ActualWidth}" x:Name="DropDown" SnapsToDevicePixels="True">
<Border x:Name="DropDownBorder" Background="White" BorderBrush="{StaticResource BorderDarkMainBrush}" BorderThickness="1" CornerRadius="0" />
<ScrollViewer Margin="2" SnapsToDevicePixels="True">
<StackPanel KeyboardNavigation.DirectionalNavigation="Contained" IsItemsHost="True" TextBlock.Foreground="Black" />
</ScrollViewer>
</Grid>
</Popup>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="HasItems" Value="false">
<Setter Property="MinHeight" TargetName="DropDownBorder" Value="95" />
</Trigger>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false" />
</Trigger>
<Trigger Property="IsEditable" Value="true">
<Setter Property="IsTabStop" Value="false" />
<Setter Property="Visibility" TargetName="PART_EditableTextBox" Value="Visible" />
<Setter Property="Visibility" TargetName="ContentSite" Value="Hidden" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
</Style.Triggers>
</Style>
Note the DataTrigger part inside the toggle button style, it hooks to its templated parent's IsKeyboardFocusWithin property istead of IsFocused property, because the last one won't work if you set the ComboBox.IsEditable to True as I did in this style.
<DataTrigger Binding="{Binding IsKeyboardFocusWithin, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=OneWay}" Value="True">
<Setter Property="Background" TargetName="Border" Value="{DynamicResource MainColorLight}" />
<Setter Property="BorderBrush" TargetName="Border" Value="{DynamicResource MainColorLight}" />
<Setter Property="BorderBrush" TargetName="Border2" Value="{DynamicResource MainColorLight}" />
<Setter Property="Fill" TargetName="Arrow" Value="White" />
</DataTrigger >

Resources