DataGridColumnHeader Style - wpf

<Style TargetType="DataGridColumnHeader">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
<Border x:Name="buttonBorderOuter"
BorderBrush="#DBDBDB"
BorderThickness="1"
Background="#00ECECEC"
Padding="2">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
<Border.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard>
...
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<BeginStoryboard>
<Storyboard>
...
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Border.Triggers>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The above code shows my Style for the DataGridColumnHeader. It's working fine with the MouseEnter and MouseLeave effect but there are some small things I don't like. There is what I have right now below here.
The problem here is that each Cell in the Header has the rounded border. I want that between 2 Cells in the Header is 1 single straight line. Also, when I click on one of the Cells in the Header, there is no arrow showing for the sorting and also no highlight that it is that column that's sorted.
Does somebody has a template I could edit myself to achieve what I want? Or what are the parts I have to edit?

By default the DataGridColumnHeadersPresenter draws an additional column Header of the full width in the Background of the DataGrid Header. By just leaving out the dummy Header you get what you want. Add that style to your styles:
<Style TargetType="{x:Type DataGridColumnHeadersPresenter}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridColumnHeadersPresenter}">
<Grid>
<ItemsPresenter />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Related

How to avoid that a Coloranimation in a ControlTemplate gets applied to every object using the template

I declared ColorAnimations inside a ControlTemplate of a Style.
What it should do:
Whenever the mouse hovers over the object the color of this specific object should be animated.
What it does instead:
Animating the color of EVERY object the style is applied to whenever I hover over one of them, even though the property activating the animation is not changing on all objects.
What I tried before:
I tried using an Eventrigger instead of a normal trigger but the problem persists.
I also tried using the "Name" property not "x:Name" but this didn't help either.
Also not using Storyboard.TargetName but Storyboard.Target and using a binding with RelativeSource to let it find the object.. and still every object using this style gets animated whenever I hover over any of them
It works as intended if I use Setters to change the background instead of Storyboards and ColorAnimations.
The Style
<Style x:Key="Fraction_ScrollViewer_ScrollBar_Thumb" TargetType="{x:Type Thumb}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Border
x:Name="Border"
CornerRadius="5"
Background="{TemplateBinding Background}"
BorderThickness="0" />
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard
Name="IsMouseOver_True"
HandoffBehavior="Compose">
<Storyboard>
<ColorAnimation
Storyboard.TargetName="Border"
Storyboard.TargetProperty="Background.(SolidColorBrush.Color)"
To="{StaticResource 'Color_CoolGrey'}"
Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard
Name="IsMouseOver_False">
<Storyboard>
<ColorAnimation
Storyboard.TargetName="Border"
Storyboard.TargetProperty="Background.(SolidColorBrush.Color)"
To="{StaticResource 'Color_MidGrey'}"
Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
The Thumb style is used in a Scrollbar style which is used in a ScrollViewer.
The Scrollviewer Style is then used in 2 locations:
1:
<Style x:Key="LabelTreeView" TargetType="{x:Type TreeView}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TreeView}">
<ScrollViewer
Style="{StaticResource ScrollViewer}"
Focusable="False"
CanContentScroll="False"
Padding="4">
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
2:
<ScrollViewer
Style="{StaticResource ScrollViewer}"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto">
<ItemsControl
BorderThickness="0"
Background="{StaticResource Brush_Transparent}"
ItemTemplate="{StaticResource CharacterSequenceChar}"
ItemsSource="{Binding DisplayedCharacterSequenceCharacters}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</ScrollViewer>
What is causing this behaviour and how to avoid it with still using animations?
Apparently all Buttons share the same Brush instance in their Background property.
You could explicitly assign a separate Brush for each Border in the Template:
<Border x:Name="Border" ...>
<Border.Background>
<SolidColorBrush Color="{Binding Background.Color,
RelativeSource={RelativeSource TemplatedParent}}"/>
</Border.Background>
</Border>

How to change button text and color on mouse enter using WPF

I'm new to WPF. I want to change button text and color on MouseEnter.
Here is my codes in order to change the color:
<Style x:Key="btnClose" TargetType="{x:Type Button}" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button" x:Name="btnClose">
<Border Name="btnCloseBorder" CornerRadius="7" Background="Red" BorderBrush="#ccc" BorderThickness="0,1,1,0" >
<ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Button.Content">
<Setter.Value>
<ContentElement ???/>
</Setter.Value>
</Setter>
</Trigger>
<EventTrigger RoutedEvent="Mouse.MouseEnter">
<BeginStoryboard>
<Storyboard>
<ColorAnimation From="Red" To="#FF7F7F" Duration="0:0:0.5" Storyboard.TargetName="btnCloseBorder" Storyboard.TargetProperty="Background.Color"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Mouse.MouseLeave">
<BeginStoryboard>
<Storyboard>
<ColorAnimation From="#FF7F7F" To="Red" Duration="0:0:0.5" Storyboard.TargetName="btnCloseBorder" Storyboard.TargetProperty="Background.Color"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Button Style="{StaticResource btnClose}" Name="btnClose" Content="" HorizontalAlignment="Left" Margin="274,0,0,0" VerticalAlignment="Top" Width="18" Height="21"/>
It works like a charm. But I couldn't change the text.
I guest it should be after ColorAnimation tag. But I dont know what tag should be used.
How can I change button text in MouseEnter and MouseLeave?
I found my answer. I simply removed Content in Button tag and changed Style like below:
<Style x:Key="btnClose" TargetType="{x:Type Button}" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button" x:Name="btnClose">
<Border Name="btnCloseBorder" CornerRadius="7" Background="Red" BorderBrush="#ccc" BorderThickness="0,1,1,0" >
<ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Button.Content" Value="Your Text">
</Setter>
</Trigger>
<EventTrigger RoutedEvent="Mouse.MouseEnter">
<BeginStoryboard>
<Storyboard >
<ColorAnimation From="Red" To="#FF7F7F" Duration="0:0:0" Storyboard.TargetName="btnCloseBorder" Storyboard.TargetProperty="Background.Color"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Mouse.MouseLeave">
<BeginStoryboard>
<Storyboard>
<ColorAnimation From="#FF7F7F" To="Red" Duration="0:0:0.5" Storyboard.TargetName="btnCloseBorder" Storyboard.TargetProperty="Background.Color"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property = "Foreground" Value="White"/>
<Setter Property = "Button.Content" Value="Some new text..."/>
</Trigger>
</Style.Triggers>
</Style>
<Button Style="{StaticResource btnClose}" Name="btnClose" HorizontalAlignment="Left" Margin="274,0,0,0" VerticalAlignment="Top" Width="18" Height="21"/>
I hope it will be useful.
You don't need to explicitly create a ContentControl. You can set Button.Content to any object you want. If the object is not a UIElement, an implicit TextBlock will be created and it's Text set to Value.ToString(). If it is a UIElement, it's OnRender method will be used to render it.
So in your case, you can simply set the setter value to a string.
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Button.Content" Value="Your Text">
</Setter>
</Trigger>
Note that this trigger will automatically revert back to the previous value when IsMouseOver becomes false.

Issue with Button Hover Image in WPF

I am attempting to change a button image when there is a mouse hover over in and I cant seem to get it to work. I have accomplished to get the blue hue to not appear when the button is hovered over but cannot get the image to change now. I have read numerous posts on it here and followed other examples but cant make it work. When I use the code below and hover over the button the image remains the same and doesn't change to the new one specified. Thoughts?
Blue Hue Removal
<Window.Resources>
<Style x:Key="ButtonStyleNoHighlighting" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Background="{TemplateBinding Background}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
Button Hover Image
<Button x:Name="btnCloseApp"
Click="Application_Close"
Style="{StaticResource ButtonStyleNoHighlighting}">
<Button.Background>
<ImageBrush ImageSource="Resources/BTN_Close.png"/>
</Button.Background>
<Button.Resources>
<ControlTemplate x:Key="BackgroundButton" TargetType="Button">
<Border Name="border" BorderThickness="1" BorderBrush="Black" Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background">
<Setter.Value>
<ImageBrush ImageSource="Resources/BTN_Close_Hover.png" />
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Resources>
</Button>
Any help would be greatly appreciated!

WPF Animation: can't bind From property to the ActualWidth

I'm trying to change a selected TabItem's width in the following way:
<Style TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid x:Name="Root">
<Border x:Name="Border" Background="{TemplateBinding Background}">
<ContentPresenter x:Name="ContentSite" VerticalAlignment="Center" HorizontalAlignment="Stretch" ContentSource="Header" Margin="12,2,12,2"/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Width"
From="{Binding RelativeSource={RelativeSource AncestorType={x:Type TabItem}, Mode=FindAncestor}, Path=ActualWidth}"
To="200"
Duration="0:0:1"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
I'm forced to specify the "From" property for the animation because I don't specify the "Width" property for the TabItem explicitly, it is calculated by the custom layout container.
But when I try to bind "From" property of the animation to the "ActualWidth" property of the TabItem, the initialization of 'System.Windows.Controls.TabItem' threws an exception. I tried to move the "Triggers" section inside the "ControlTemplate" section, but with no effect. So I have 2 questions:
1) Why can't the "From" property be bound to the ActualWidth of the TabItem in the way I did it?
2) How can I achieve the desired behaviour?
Any hints would be appreciated.
This cannot be done because WPF framework will freeze the things which would used for the Animation by initially and So if you are trying to Bind on a Freezable, it doest accept that. That's why it was prevented from changing and says,
Cannot freeze this Storyboard timeline tree for use across threads

WPF Trigger animation when Visibility is changed?

Well i have a custom control and when Visibility is changed to Visible I have a Trigger with a enter/exit action but the problem is that when the exit action fires the Visibility is no longer Visible so the animation can't be seen how would I fix this?
here is my Trigger:
<ControlTemplate.Triggers>
<Trigger Property="Visibility" Value="Visible">
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource Hide}"/>
</Trigger.ExitActions>
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource Show}"/>
</Trigger.EnterActions>
</Trigger>
</ControlTemplate.Triggers>
I tried this too and failed. I think it is not possible to accomplish this in a simple ControlTemplate with a Trigger on the Visibility property. What you can do is add an Opacity animation From 1 To 0 to a Trigger for a different property, for instance a DependencyProperty that you add in the code behind yourself.
You could also use ObjectAnimationUsingKeyFrames to set Visibility for animation period.
In such case there is no need in any codebehind.
There is a way to achieve it. Not 100 % pure, but works for me:
Don't use Visibility property, but use Opacity and Tag property.
<ListView.Resources>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border CornerRadius="5"
BorderThickness="2"
BorderBrush="DodgerBlue"
Background="#CC4f9dea" >
<Grid>
<ContentPresenter HorizontalAlignment="Stretch" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Stretch" />
<Button x:Name="btnClose" Opacity="0" Content="X" Style="{StaticResource RoundedButtonStyle}"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Tag" TargetName="btnClose" Value="Visible" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.Resources>
<Style x:Key="RoundedButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border CornerRadius="15" Background="White" BorderThickness="1" Padding="2" BorderBrush="Black">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Tag" Value="Visible">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity"
From="0.0" To="0.5" Duration="0:0:0.5"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity"
From="0.5" To="0.0" Duration="0:0:0.5"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>

Resources