Inheritance of templates in WPF
- by Alxandr
I'm trying to make sure that every child of a given element (MPF.MWindow) gets custom templates. For instance, the button should get the template defined in resMButton.xaml. As of now I'm using the following code on: (resMWindow.xaml)
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MPF">
<Style x:Key="SystemKeyAnimations" TargetType="{x:Type Button}">
<Setter Property="Opacity" Value="0.5" />
<Setter Property="Background" Value="Transparent" />
<Style.Triggers>
<EventTrigger RoutedEvent="Mouse.MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetProperty="Opacity">
<SplineDoubleKeyFrame KeyTime="00:00:00.2" Value="1.0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Mouse.MouseLeave">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetProperty="Opacity">
<SplineDoubleKeyFrame KeyTime="00:00:00.2" Value="0.5" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type local:MWindow}">
<!-- Remove default frame appearance -->
<Setter Property="WindowStyle" Value="None" />
<Setter Property="AllowsTransparency" Value="True" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MWindow}">
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}" x:Name="ChromeBorder">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4" />
<ColumnDefinition />
<ColumnDefinition Width="4" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="4" />
<RowDefinition />
<RowDefinition Height="4" />
</Grid.RowDefinitions>
<Thumb Grid.Row="0" Grid.Column="1" x:Name="TopThumb" Cursor="SizeNS" BorderThickness="4" BorderBrush="Transparent" />
<Thumb Grid.Row="2" Grid.Column="1" x:Name="BottomThumb" Cursor="SizeNS" BorderThickness="4" BorderBrush="Transparent" />
<Thumb Grid.Row="1" Grid.Column="0" x:Name="LeftThumb" Cursor="SizeWE" BorderThickness="4" BorderBrush="Transparent" />
<Thumb Grid.Row="1" Grid.Column="2" x:Name="RightThumb" Cursor="SizeWE" BorderThickness="4" BorderBrush="Transparent" />
<Thumb Grid.Row="0" Grid.Column="0" x:Name="TopLeftThumb" Cursor="SizeNWSE" BorderThickness="5" BorderBrush="Transparent" />
<Thumb Grid.Row="0" Grid.Column="2" x:Name="TopRightThumb" Cursor="SizeNESW" BorderThickness="5" BorderBrush="Transparent" />
<Thumb Grid.Row="2" Grid.Column="0" x:Name="BottomLeftThumb" Cursor="SizeNESW" BorderThickness="5" BorderBrush="Transparent" />
<Thumb Grid.Row="2" Grid.Column="2" x:Name="BottomRightThumb" Cursor="SizeNWSE" BorderThickness="5" BorderBrush="Transparent" />
<Grid Grid.Row="1" Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="20" />
<RowDefinition />
</Grid.RowDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal" Grid.Column="1">
<Button Command="local:WindowCommands.Minimize" Style="{StaticResource ResourceKey=SystemKeyAnimations}">
<Button.Template>
<ControlTemplate>
<Canvas Width="10" Height="10" Margin="5" Background="Transparent">
<Line X1="0" X2="10" Y1="5" Y2="5" Stroke="White" StrokeThickness="2" />
</Canvas>
</ControlTemplate>
</Button.Template>
</Button>
<Button Command="local:WindowCommands.Maximize" x:Name="MaximizeButton" Style="{StaticResource ResourceKey=SystemKeyAnimations}">
<Button.Template>
<ControlTemplate>
<Canvas Width="10" Height="10" Margin="5" Background="Transparent">
<Rectangle Width="10" Height="10" Stroke="White" StrokeThickness="2" />
</Canvas>
</ControlTemplate>
</Button.Template>
</Button>
<Button Command="ApplicationCommands.Close" Style="{StaticResource ResourceKey=SystemKeyAnimations}">
<Button.Template>
<ControlTemplate>
<Canvas Width="10" Height="10" Margin="5" Background="Transparent">
<Line X1="0" X2="10" Y1="0" Y2="10" Stroke="White" StrokeThickness="2" />
<Line X1="10" X2="0" Y1="0" Y2="10" Stroke="White" StrokeThickness="2" />
</Canvas>
</ControlTemplate>
</Button.Template>
</Button>
</StackPanel>
<ContentControl x:Name="TitleContentControl">
<TextBlock Text="{TemplateBinding Title}" Foreground="DarkGray" Margin="5,0" />
</ContentControl>
</Grid>
<ContentPresenter Content="{TemplateBinding Content}" Grid.Row="1">
<ContentPresenter.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/MPF;component/Themes/resMWindowContent.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</ContentPresenter.Resources>
</ContentPresenter>
</Grid>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
As you can see during the ContentPresenter which gets the content of the window I merge in a dicrionary called resMWindowContent.xaml. The resMWindowContent.xaml looks as following:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MPF">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/MPF;component/Themes/resMButton.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
It simply merges in the resMButton.xaml dictionary (this is done because in the feature I will have MTextBox, mList... and I want to separate them).
The resMButton.xaml looks as following:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MPF">
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid Background="Transparent">
<Rectangle Stroke="{TemplateBinding BorderBrush}" StrokeThickness="{TemplateBinding BorderThickness}"
Fill="{TemplateBinding Background}" />
<ContentPresenter Content="{TemplateBinding Content}" Margin="3" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
A simple template drawing a square button. However, it isn't applied at all. My buttons remain normal, and I don't understand what I'm doing wrong. I just want every button inside the MWindow to get a special style (and in time every textbox and so forth). How do I achieve this?
One note though: It's important that the styles doesn't apply to elements outside an MWindow.