In this animated ToggleButton ControlTemplate, upon clicking it does it's animation which rotates the Path when IsChecked is changed.
<ControlTemplate x:Key="AnimatedExpanderButtonTemp" TargetType="{x:Type ToggleButton}">
<Border x:Name="ExpanderButtonBorder"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Rectangle Fill="Transparent"/>
<Ellipse x:Name="Circle"
Grid.Column="0"
Stroke="DarkGray"
Fill="White"
Width="15"
Height="15"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
<Path x:Name="Arrow"
Grid.Column="0"
Data="M 1,1.5 L 4.5,5 8,1.5"
Stroke="#FF666666"
StrokeThickness="2"
HorizontalAlignment="Center"
VerticalAlignment="Center"
RenderTransformOrigin="0.5,0.5">
</Path>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="Arrow"
Storyboard.TargetProperty="(UIElement.RenderTransform).(RotateTransform.Angle)"
To="180"
Duration="0:0:0.4"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="Arrow"
Storyboard.TargetProperty="(UIElement.RenderTransform).(RotateTransform.Angle)"
To="0"
Duration="0:0:0.4"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
However there are conditions where I don't want the animation to play out.
Such when the ToggleButton is first loaded and it is pre-checked,
or,
if using it in a VirtualizingPanel and the button row goes out of scope and comes back in again.
Some scenerios:
1) If it is pre-checked and not from a click then it goes straight to rotating the Arrow 180 degrees without animation.
2) If it is clicked and Checked is True, it rotates to 180 animated.
3) If it is clicked and Checked is False, it rotates to 0 animated.
How can I accomplish this?
Try something like this:
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsChecked" Value="True" />
<Condition Property="IsPressed" Value="False" />
<!--<Condition Property="IsMouseOver" Value="False" /> not sure if needed in your case-->
</MultiTrigger.Conditions>
<!--your logic for changing without animation-->
<!--<Setter Property="" Value="" />-->
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsChecked" Value="True" />
<Condition Property="IsPressed" Value="True" />
<!--<Condition Property="IsMouseOver" Value="False" /> not sure if needed in your case-->
</MultiTrigger.Conditions>
<!--your logic for changing with animation-->
<!--<Setter Property="" Value="" />-->
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsChecked" Value="False" />
<Condition Property="IsPressed" Value="True" />
<!--<Condition Property="IsMouseOver" Value="False" /> not sure if needed in your case-->
</MultiTrigger.Conditions>
<!--your logic for changing with animation-->
<!--<Setter Property="" Value="" />-->
</MultiTrigger>
</ControlTemplate.Triggers>
Related
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.
I attempted to create a simple style for a TabItem, by going to the Properties window and converting the template to a new resource, and wrapping it in a style (pretty standard stuff).
The goal is to animate the BorderBrush colour based on the IsSelected property. I've actually done this with relative ease, using the original generated code as a basis.
The problem: In the designer and when the application starts, all TabItems show as selected until I click on any tab which isn't the first one (index 0, since that's selected by default).
A screen recording demonstrating what happens:
https://i.gyazo.com/17e2f3c484029d4f5cd3021612b0f882.mp4
How can this be remedied? I have tried using the various trigger types and none seem to fix the problem.
The style code:
<Style TargetType="{x:Type TabItem}">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="Padding" Value="8,0"/>
<Setter Property="Height" Value="30"/>
<Setter Property="Margin" Value="0,0,1,0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Border x:Name="ElementBorder" Height="30" Width="Auto" Background="#FF1F1F1F" BorderBrush="#FF00FF96" BorderThickness="0,0,0,2" CornerRadius="2,2,0,0" SnapsToDevicePixels="True">
<ContentPresenter TextBlock.Foreground="Silver"
ContentTemplate="{TemplateBinding HeaderTemplate}"
Content="{TemplateBinding Header}"
ContentStringFormat="{TemplateBinding HeaderStringFormat}"
ContentSource="Header"
HorizontalAlignment="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type ItemsControl}}}"
Margin="{TemplateBinding Padding}"
RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{Binding VerticalContentAlignment, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type ItemsControl}}}"/>
</Border>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="True"/>
</MultiTrigger.Conditions>
<MultiTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetName="ElementBorder"
Storyboard.TargetProperty="(Control.BorderBrush).(SolidColorBrush.Color)"
To="#FF00FF96"
Duration="0:0:0.1"/>
</Storyboard>
</BeginStoryboard>
</MultiTrigger.EnterActions>
<MultiTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetName="ElementBorder"
Storyboard.TargetProperty="(Control.BorderBrush).(SolidColorBrush.Color)"
To="#FF1F1F1F"
Duration="0:0:0.1"/>
</Storyboard>
</BeginStoryboard>
</MultiTrigger.ExitActions>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The problem is that you set your default BorderBrush to be the selected color. Change it to be the unselected color like so:
<Border x:Name="ElementBorder"
Width="Auto"
Height="30"
Background="#FF1F1F1F"
BorderBrush="#FF1F1F1F"
BorderThickness="0,0,0,2"
CornerRadius="2,2,0,0"
SnapsToDevicePixels="True">
Also, you can simplify your trigger:
<Trigger Property="IsSelected" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetName="ElementBorder"
Storyboard.TargetProperty="(Control.BorderBrush).(SolidColorBrush.Color)"
To="#FF00FF96"
Duration="0:0:0.1" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetName="ElementBorder"
Storyboard.TargetProperty="(Control.BorderBrush).(SolidColorBrush.Color)"
To="#FF1F1F1F"
Duration="0:0:0.1" />
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
.Net 4 WPF DataGrid C# MMVM
When the DataGrid SelectionUnit is full row, wpf databinding and the collectionview take care of letting me know in the viewmodel what is the actively selected item via the view's currentitem property. This works great for readonly grids with the selection mode set to the fullrow.
Now I have an editable grid. So I set the SelectionUnit=Cell to make it easier to spot which cell one is in. Now all of a sudden the grid no longer has any ability to track the selection item. I can't even set SelectedItem when set to cell mode. So now the viewmodel always thinks it's on the first row. I can handle SelectedCellsChanged in the grid to figure out what row I'm on, I just have no way of letting the viewmodel know since the grid's SelectedItem can no longer be set!
I don't understand why the grid can't still have a SelectedItem when in cell select mode.
Short of hardcoding into my grid to cast the ItemSource to my collectionview to call MoveCurrentTo from the SelectedCellsChanged event, is there any other MVVM true way to keep the view's CurrentItem in sync with the grid?
Either that, or I change the grid style to remove or reduce the row highlight effect when I have an editable grid.
I was searching for the same problems and found a simple solution
To access to the row with SelectionUnit set to Cell you have to do:
DataGridXX.SelectedCells[0].item
It works only if you can select only one cell at time (not in Extended mode).
I found a great solution for this on MSDN using attached properties:
<DataGrid ItemsSource="{Binding}" IsReadOnly="True" SelectionUnit="Cell">
<DataGrid.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="local:DataGridAttachedProperties.IsCellSelected" Value="True"/>
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter Property="local:DataGridAttachedProperties.IsCellSelected" Value="False"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.CellStyle>
<DataGrid.ItemContainerStyle>
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<Trigger Property="local:DataGridAttachedProperties.IsCellSelected" Value="True">
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="BorderBrush" Value="Red"/>
<Setter Property="Background" Value="Yellow"/>
<Setter Property="Opacity" Value="0.7"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.ItemContainerStyle>
</DataGrid>
And the C#:
public class DataGridAttachedProperties
{
public static bool GetIsCellSelected(DependencyObject obj)
{
return (bool)obj.GetValue(IsCellSelectedProperty);
}
public static void SetIsCellSelected(DependencyObject obj, bool value)
{
obj.SetValue(IsCellSelectedProperty, value);
}
public static readonly DependencyProperty IsCellSelectedProperty =
DependencyProperty.RegisterAttached("IsCellSelected", typeof(bool), typeof(DataGridAttachedProperties), new UIPropertyMetadata(false,
(o, e) =>
{
if (o is DataGridCell)
{
DataGridRow row = VisualTreeHelperEx.FindVisualParent<DataGridRow>(o as DataGridCell);
row.SetValue(DataGridAttachedProperties.IsCellSelectedProperty, e.NewValue);
}
}));
}
public class VisualTreeHelperEx
{
public static T FindVisualParent<T>(DependencyObject child)
where T : DependencyObject
{
DependencyObject parentObject = VisualTreeHelper.GetParent(child);
if (parentObject == null) return null;
T parent = parentObject as T;
if (parent != null)
{
return parent;
}
else
{
return FindVisualParent<T>(parentObject);
}
}
}
i too Have a similar problem, so here is the Style i used(Copied from Net).
So you copy the WhistlerBlue theme from http://datagridthemesfromsl.codeplex.com/ and make following modifications. Hope this helps.
<!--Cell-->
<Style x:Key='CellStyle' TargetType="{x:Type controls:DataGridCell}" >
<Setter Property="Foreground" Value="{StaticResource ThemeForegroundBrush}" />
<Setter Property="Height" Value="Auto" />
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="Cursor" Value="Arrow" />
<Setter Property="BorderThickness" Value="1" />
<!--Padding hack-->
<Setter Property="Padding" Value="2 5 2 5" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls:DataGridCell}">
<Grid x:Name="Root" Background="Transparent">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Rectangle x:Name="FocusVisual" Margin="0,-2,0,0"
Stroke="White" Fill="White"
Opacity="0" IsHitTestVisible="false"/>
<ContentPresenter Margin="{TemplateBinding Padding}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}" Cursor="{TemplateBinding Cursor}"/>
<Rectangle x:Name="RightGridLine" VerticalAlignment="Stretch" Width="1" Grid.Column="1" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- DataGridRow -->
<Style x:Key='RowStyle' TargetType="{x:Type controls:DataGridRow}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls:DataGridRow}">
<Border x:Name="DGR_Border"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="True">
<primitives:SelectiveScrollingGrid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height='Auto' />
</Grid.RowDefinitions>
<Rectangle x:Name="Selected" Margin="0" Grid.RowSpan="2" Grid.ColumnSpan="2"
Fill="{StaticResource BtnOverFill}" Stroke="{StaticResource selectedStroke}"
Opacity="0"/>
<Rectangle x:Name="SelectedHighlight" Margin="1" Grid.RowSpan="2" Grid.ColumnSpan="2"
Stroke="#A0FFFFFF"
Opacity="0"/>
<primitives:DataGridRowHeader Grid.RowSpan="2"
primitives:SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical"
Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type controls:DataGrid}},
Path=HeadersVisibility,
Converter={x:Static controls:DataGrid.HeadersVisibilityConverter},
ConverterParameter={x:Static controls:DataGridHeadersVisibility.Row}}"/>
<Rectangle x:Name="Over" Margin="0" Grid.RowSpan="2" Grid.ColumnSpan="2"
Fill="{StaticResource hoverGradient}"
Stroke="{StaticResource hoverStroke}"
Opacity="0"/>
<primitives:DataGridCellsPresenter Grid.Column="1"
ItemsPanel="{TemplateBinding ItemsPanel}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
<primitives:DataGridDetailsPresenter Grid.Column="1" Grid.Row="1"
x:Name='DetailsPresenter'
primitives:SelectiveScrollingGrid.SelectiveScrollingOrientation="{Binding RelativeSource={RelativeSource AncestorType={x:Type controls:DataGrid}}, Path=AreRowDetailsFrozen, Converter={x:Static controls:DataGrid.RowDetailsScrollingConverter}, ConverterParameter={x:Static controls:SelectiveScrollingOrientation.Vertical}}"
Visibility="{TemplateBinding DetailsVisibility}"
/>
<Rectangle Height="1" HorizontalAlignment="Stretch"
x:Name="BottomGridLine"
Fill="{StaticResource HorizontalVerticalGridLinesBrush}"
Grid.Column="1" Grid.Row="2" />
</primitives:SelectiveScrollingGrid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property='IsSelected' Value='True'>
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0" Storyboard.TargetName="Selected" Storyboard.TargetProperty="Opacity" To="0.84"/>
<DoubleAnimation Duration="0" Storyboard.TargetName="SelectedHighlight" Storyboard.TargetProperty="Opacity" To="1"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0" Storyboard.TargetName="Selected" Storyboard.TargetProperty="Opacity" To="0"/>
<DoubleAnimation Duration="0" Storyboard.TargetName="SelectedHighlight" Storyboard.TargetProperty="Opacity" To="0"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
<!--<Setter Property="DetailsVisibility" Value="Visible" />-->
</Trigger>
<MultiTrigger >
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True" />
<Condition Property="IsSelected" Value="False" />
</MultiTrigger.Conditions>
<MultiTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0" Storyboard.TargetName="Over" Storyboard.TargetProperty="Opacity" To="0.73"/>
</Storyboard>
</BeginStoryboard>
</MultiTrigger.EnterActions>
<MultiTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0" Storyboard.TargetName="Over" Storyboard.TargetProperty="Opacity" To="0"/>
</Storyboard>
</BeginStoryboard>
</MultiTrigger.ExitActions>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="True" />
<Condition Property="IsFocused" Value="False" />
</MultiTrigger.Conditions>
<MultiTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0" Storyboard.TargetName="Selected" Storyboard.TargetProperty="Opacity" To="0.84"/>
<DoubleAnimation Duration="0" Storyboard.TargetName="SelectedHighlight" Storyboard.TargetProperty="Opacity" To="1"/>
</Storyboard>
</BeginStoryboard>
</MultiTrigger.EnterActions>
<MultiTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0" Storyboard.TargetName="Selected" Storyboard.TargetProperty="Opacity" To="0"/>
<DoubleAnimation Duration="0" Storyboard.TargetName="SelectedHighlight" Storyboard.TargetProperty="Opacity" To="0"/>
</Storyboard>
</BeginStoryboard>
</MultiTrigger.ExitActions>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I have included the following style for ComboBox, which I happened to find as part of WPFToolkit some year ago.
It lacks one basic funcionality, that is, if I click inside the TextBox of the ComboBox, I want the dropdown menu to expand as usual. In this template the dropdown menu can only be opened by clicking the ComboBoxToggleButton directly.
I have no clue what to look for in the template style, can you please direct me somehow?
Template style:
<ControlTemplate x:Key="ComboBoxToggleButton"
TargetType="{x:Type ToggleButton}">
<ControlTemplate.Resources>
<Storyboard x:Key="HoverOn">
<DoubleAnimation Duration="00:00:00.1000000"
Storyboard.TargetName="rectangleOver"
Storyboard.TargetProperty="Opacity"
To="0.8" />
<ColorAnimation Duration="00:00:00.1000000"
Storyboard.TargetName="Background"
Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"
To="#FFFFFFFF" />
</Storyboard>
<Storyboard x:Key="HoverOff">
<DoubleAnimation Duration="00:00:00.4000000"
Storyboard.TargetName="rectangleOver"
Storyboard.TargetProperty="Opacity"
To="0" />
<ColorAnimation Duration="00:00:00.4000000"
Storyboard.TargetName="Background"
Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"
To="#FFffffff" />
</Storyboard>
<Storyboard x:Key="PressedOn">
<DoubleAnimation Duration="00:00:00.1000000"
Storyboard.TargetName="rectanglePress"
Storyboard.TargetProperty="Opacity"
To="0.8" />
<ColorAnimation Duration="00:00:00.1000000"
Storyboard.TargetName="Background"
Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"
To="#FFFFFFFF" />
</Storyboard>
<Storyboard x:Key="PressedOff">
<DoubleAnimation Duration="00:00:00.4000000"
Storyboard.TargetName="rectanglePress"
Storyboard.TargetProperty="Opacity"
To="0" />
<ColorAnimation Duration="00:00:00.4000000"
Storyboard.TargetName="Background"
Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"
To="#FFffffff" />
</Storyboard>
<Storyboard x:Key="CheckedOn">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="BackgroundChecked"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.1000000"
Value="1" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="CheckedOff">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="BackgroundChecked"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.3000000"
Value="0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</ControlTemplate.Resources>
<Grid x:Name="grid">
<Rectangle x:Name="Background"
Fill="#ffffff"
Stroke="#ffc6c6c6"
RadiusX="3"
RadiusY="3"
IsHitTestVisible="false" />
<Rectangle x:Name="BackgroundChecked"
Margin="1"
IsHitTestVisible="false"
Opacity="0">
<Rectangle.Fill>
<SolidColorBrush Color="{DynamicResource WhiteColor}" />
</Rectangle.Fill>
</Rectangle>
<Rectangle x:Name="rectangleOver"
Width="15"
Stroke="#FFE8E8E8"
HorizontalAlignment="Right"
Opacity="0"
Fill="{DynamicResource MouseOverBrush}" />
<Rectangle x:Name="rectanglePress"
Width="15"
Stroke="#FC9E9D9B"
HorizontalAlignment="Right"
Opacity="0"
Fill="{DynamicResource PressedBrush}" />
<Rectangle x:Name="DisabledVisualElement"
Margin="1"
Fill="{DynamicResource DisabledBackgroundBrush}"
IsHitTestVisible="false"
Visibility="Collapsed" />
<Path x:Name="BtnArrow"
Margin="0,0,4,0"
Width="6"
Fill="{DynamicResource GlyphBrush}"
Stretch="Uniform"
HorizontalAlignment="Right"
Data="F1 M 301.14,-189.041L 311.57,-189.041L 306.355,-182.942L 301.14,-189.041 Z " />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsPressed"
Value="True">
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource PressedOff}"
x:Name="PressedOff_BeginStoryboard" />
</Trigger.ExitActions>
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource PressedOn}"
x:Name="PressedOn_BeginStoryboard" />
</Trigger.EnterActions>
</Trigger>
<Trigger Property="IsMouseOver"
Value="true">
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource HoverOff}"
x:Name="HoverOff_BeginStoryboard" />
</Trigger.ExitActions>
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource HoverOn}" />
</Trigger.EnterActions>
</Trigger>
<Trigger Property="IsChecked"
Value="true">
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource CheckedOff}"
x:Name="CheckedOff_BeginStoryboard" />
</Trigger.ExitActions>
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource CheckedOn}"
x:Name="CheckedOn_BeginStoryboard" />
</Trigger.EnterActions>
</Trigger>
<Trigger Property="IsEnabled"
Value="False">
<Setter Property="Foreground"
Value="{DynamicResource DisabledForegroundBrush}" />
<Setter Property="Visibility"
TargetName="DisabledVisualElement"
Value="Visible" />
<Setter Property="Fill"
TargetName="Background"
Value="{DynamicResource DisabledBackgroundBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<ControlTemplate x:Key="ComboBoxTextBox"
TargetType="{x:Type TextBox}">
<Border x:Name="PART_ContentHost"
Focusable="False"
Background="{TemplateBinding Background}" />
</ControlTemplate>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="SnapsToDevicePixels"
Value="true" />
<Setter Property="HorizontalContentAlignment"
Value="Stretch" />
<Setter Property="VerticalContentAlignment"
Value="Center" />
<Setter Property="FontSize"
Value="13" />
<Setter Property="FontWeight"
Value="Bold" />
<Setter Property="Padding"
Value="6,2,25,2" />
<Setter Property="Margin"
Value="3" />
<Setter Property="ToolTipService.ShowOnDisabled"
Value="True" />
<Setter Property="Template"
Value="{DynamicResource ComboBoxTemplate}" />
<Setter Property="Validation.ErrorTemplate"
Value="{StaticResource SablonaChybovehoHlaseni}" />
</Style>
<ControlTemplate x:Key="ComboBoxTemplate"
TargetType="{x:Type ComboBox}">
<ControlTemplate.Resources>
<Storyboard x:Key="FocusedOn">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="FocusVisualElement"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.1000000"
Value="1" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="FocusedOff">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="FocusVisualElement"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.3000000"
Value="0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</ControlTemplate.Resources>
<Grid>
<ToggleButton Grid.Column="2"
Template="{DynamicResource ComboBoxToggleButton}"
x:Name="ToggleButton"
Focusable="false"
IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
ClickMode="Press" />
<ContentPresenter HorizontalAlignment="Stretch"
Margin="3,3,23,3"
x:Name="ContentSite"
VerticalAlignment="Top"
Content="{TemplateBinding SelectionBoxItem}"
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
IsHitTestVisible="True">
<ContentPresenter.ContentTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"
TextWrapping="Wrap" />
</DataTemplate>
</ContentPresenter.ContentTemplate>
</ContentPresenter>
<!--Textbox for ComboBox-->
<!--Set transparent background of TextBox-->
<TextBox Visibility="Hidden"
Template="{DynamicResource ComboBoxTextBox}"
HorizontalAlignment="Stretch"
Margin="3,3,23,3"
x:Name="PART_EditableTextBox"
Style="{x:Null}"
VerticalAlignment="Top"
Focusable="True"
Background="Transparent"
TextWrapping="Wrap"
IsReadOnly="{TemplateBinding IsReadOnly}" />
<Rectangle x:Name="DisabledVisualElement"
Fill="{DynamicResource DisabledBackgroundBrush}"
Stroke="{DynamicResource DisabledBorderBrush}"
RadiusX="3"
RadiusY="3"
IsHitTestVisible="false"
Opacity="0" />
<Rectangle x:Name="FocusVisualElement"
Margin="-1"
RadiusX="3"
RadiusY="3"
Stroke="{DynamicResource FocusBrush}"
StrokeThickness="1"
IsHitTestVisible="false"
Opacity="0" />
<Popup IsOpen="{TemplateBinding IsDropDownOpen}"
Placement="Bottom"
x:Name="Popup"
Focusable="False"
AllowsTransparency="True"
PopupAnimation="Slide"
Margin="0,1,0,0">
<Grid MaxHeight="{TemplateBinding MaxDropDownHeight}"
MinWidth="{TemplateBinding ActualWidth}"
x:Name="DropDown"
SnapsToDevicePixels="True">
<Border x:Name="DropDownBorder"
Margin="0,-1,0,0"
BorderBrush="{DynamicResource ControlBorderBrush}"
BorderThickness="1"
CornerRadius="0,0,3,3"
Background="{DynamicResource WhiteColorBrush}">
<!--ControlBackgroundBrush-->
<ScrollViewer Margin="4,6,4,6"
SnapsToDevicePixels="True"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto"
CanContentScroll="True">
<StackPanel IsItemsHost="True"
KeyboardNavigation.DirectionalNavigation="Contained" />
</ScrollViewer>
</Border>
</Grid>
</Popup>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused"
Value="True">
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource FocusedOff}"
x:Name="FocusedOff_BeginStoryboard" />
</Trigger.ExitActions>
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource FocusedOn}" />
</Trigger.EnterActions>
<Setter Property="CornerRadius"
TargetName="DropDownBorder"
Value="3" />
</Trigger>
<Trigger Property="HasItems"
Value="false">
<Setter Property="MinHeight"
Value="95"
TargetName="DropDownBorder" />
</Trigger>
<Trigger Property="IsEnabled"
Value="false">
<Setter Property="Foreground"
Value="{DynamicResource DisabledForegroundBrush}" />
<Setter Property="Opacity"
TargetName="DisabledVisualElement"
Value="1" />
</Trigger>
<Trigger Property="IsGrouping"
Value="true">
<Setter Property="ScrollViewer.CanContentScroll"
Value="false" />
</Trigger>
<Trigger Property="AllowsTransparency"
SourceName="Popup"
Value="true">
<Setter Property="CornerRadius"
Value="4"
TargetName="DropDownBorder" />
<Setter Property="Margin"
Value="0,2,0,0"
TargetName="DropDownBorder" />
</Trigger>
<Trigger Property="IsEditable"
Value="true">
<Setter Property="IsTabStop"
Value="false" />
<Setter Property="Visibility"
Value="Visible"
TargetName="PART_EditableTextBox" />
<Setter Property="Visibility"
Value="Hidden"
TargetName="ContentSite" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
There are two use cases for the ComboBox. The first is when IsEditable is false. In this case, the user is restricted to selecting a predefined item. The second is when IsEditable is true, and this case allows the user to enter text as well as select a predefined item.
With the default Aero style, clicking in the "text" area (i.e. when IsEditable is true) does not bring up the drop-down. Clicking focuses/select the text instead. The other styles will open the drop-down though.
To accomplish this there is a transparent ToggleButton placed on top of the other control, which toggles the drop-down visibility. Something like:
<Grid Grid.IsSharedSizeScope="true">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"
SharedSizeGroup="ComboBoxButton"/>
</Grid.ColumnDefinitions>
<TextBox x:Name="PART_EditableTextBox"
Grid.Column="1"
Style="{StaticResource ComboBoxEditableTextBox}"
IsReadOnly="{Binding Path=IsReadOnly,RelativeSource={RelativeSource TemplatedParent}}"
Margin="{TemplateBinding Padding}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
<ToggleButton Background="{x:Null}"
Grid.ColumnSpan="3"
Style="{StaticResource ComboBoxTransparentButtonStyle}"
IsChecked="{Binding Path=IsDropDownOpen,Mode=TwoWay,RelativeSource={RelativeSource TemplatedParent}}"/>
</Grid>
This was pull from the default Style for Luna, which you can get from here (or download directly from here).
How would I go about changing a TabItem color from it's unselected color to it's selected color with an animation on SelectionChanged, so that both the unselected and selected TabItems change?
Edit: This is how my CustomTemplate looks like. There is no animation happening at all so what have I done wrong?
<Style TargetType="TabItem">
<Setter Property="IsEnabled" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabItem">
<Grid>
<Border BorderBrush="Transparent" BorderThickness="0" MinWidth="120">
<StackPanel Orientation="Vertical">
<ContentPresenter HorizontalAlignment="Center" ContentSource="Header" />
<Ellipse Name="Ellipse" Stroke="Black" StrokeThickness="1" Width="24" Height="24" Margin="5" Fill="Transparent" />
</StackPanel>
</Border>
</Grid>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="True" />
<Condition Property="Ellipse.Fill" Value="Transparent" />
</MultiTrigger.Conditions>
<MultiTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetName="Ellipse" Storyboard.TargetProperty="Fill"
From="Transparent" To="Orange" Duration="0:0:1" />
</Storyboard>
</BeginStoryboard>
</MultiTrigger.EnterActions>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="False" />
<Condition Property="Ellipse.Fill" Value="Orange" />
</MultiTrigger.Conditions>
<MultiTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetName="Ellipse" Storyboard.TargetProperty="Fill"
From="Orange" To="Transparent" Duration="0:0:1" />
</Storyboard>
</BeginStoryboard>
</MultiTrigger.EnterActions>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
You can define custom TabItem template and run animations using triggers.