Reputation: 817
I'm quite new to WPF. Below is what I tried to do in order to use the same controlTemplate
to buttons that the only difference between them is the PathGeometry
value.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Shared.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style TargetType="Button" x:Key="buttonHeader">
<Setter Property="Width" Value="18" />
<Setter Property="Height" Value="18" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="BorderStyle" Background="Transparent" >
<Path
x:Name="CheckMark"
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
SnapsToDevicePixels="False"
Stroke="#FF4D4D4D"
StrokeThickness="2" StrokeEndLineCap="Flat" StrokeStartLineCap="Flat"
Data="{DynamicResource geoPath}">
</Path>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="BorderStyle" Property="Background" Value="#B2FFFFFF" />
<Setter TargetName="CheckMark" Property="Stroke" Value="#D8727272" />
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter TargetName="BorderStyle" Property="Background" Value="#B2707070" />
<Setter TargetName="CheckMark" Property="Stroke" Value="#D8FFFFFF" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<PathGeometry x:Key="X_Sign">
<PathFigure StartPoint="0,0">
<LineSegment Point="10,10"/>
</PathFigure>
<PathFigure StartPoint="0,10">
<LineSegment Point="10,0"/>
</PathFigure>
</PathGeometry>
<PathGeometry x:Key="Min_Sign">
<PathFigure StartPoint="0,0">
<LineSegment Point="10,0"/>
</PathFigure>
</PathGeometry>
<Style x:Key="ButtonX" BasedOn="{StaticResource buttonHeader}" TargetType="Button">
<Style.Resources>
<StaticResource x:Key="geoPath" ResourceKey="X_Sign"/>
</Style.Resources>
</Style>
<Style x:Key="ButtonXMinimize" BasedOn="{StaticResource buttonHeader}" TargetType="Button">
<Style.Resources>
<StaticResource x:Key="geoPath" ResourceKey="Min_Sign"/>
</Style.Resources>
</Style>
</ResourceDictionary>
In the designer I actually get exactly what I want, but when I try to run the application i get a XamlParseException
and the innerException is:
Unable to cast object of type 'System.Windows.Media.PathGeometry' to type 'System.Windows.ResourceDictionary'
What am I missing and how can I fix it? Also, I'll be happy to know if there is a better way to do it.
Thanks in advance.
Upvotes: 1
Views: 380
Reputation: 7734
Although passing a resource directly through StaticResource doesn't work reliably, XAML elements can usually be broken down further into reusable parts. If you look at the PathGeometry class declaration, you'll notice it has:
[ContentPropertyAttribute("Figures")]
which means the Figures
property is what actually gets set when you nest a child in XAML. The type of this property is PathFigureCollection, which your PathFigure
elements are being added to. This means you could store the PathFigureCollection
itself as a resource:
<PathFigureCollection x:Key="XSignFigures">
<PathFigure StartPoint="0,0">
<LineSegment Point="10,10"/>
</PathFigure>
<PathFigure StartPoint="0,10">
<LineSegment Point="10,0"/>
</PathFigure>
</PathFigureCollection>
and then apply it to a PathGeometry
when you need it:
<Style x:Key="ButtonX" BasedOn="{StaticResource buttonHeader}" TargetType="Button">
<Style.Resources>
<PathGeometry x:Key="geoPath" Figures="{StaticResource ResourceKey=XSignFigures}" />
</Style.Resources>
</Style>
More info: http://msdn.microsoft.com/en-us/library/ms788723.aspx#collection_syntax
Upvotes: 1
Reputation: 13047
You can't use a StaticResource
as a "proxy" for an actual resource (here: PathGeometry
) like that.
What you can do is move each PathGeometry
into its corresponding <Style.Resources>
section. Thus you won't have any PathGeometries called "X_Sign" or "Min_Sign" - just two that are called "geoPath":
...
<Style x:Key="ButtonX" BasedOn="{StaticResource buttonHeader}" TargetType="Button">
<Style.Resources>
<!--<StaticResource x:Key="geoPath" ResourceKey="X_Sign"/>-->
<PathGeometry x:Key="geoPath">
<PathFigure StartPoint="0,0">
<LineSegment Point="10,10"/>
</PathFigure>
<PathFigure StartPoint="0,10">
<LineSegment Point="10,0"/>
</PathFigure>
</PathGeometry>
</Style.Resources>
</Style>
<Style x:Key="ButtonXMinimize" BasedOn="{StaticResource buttonHeader}" TargetType="Button">
<Style.Resources>
<ResourceDictionary>
<!--<StaticResource x:Key="geoPath" ResourceKey="Min_Sign"/>-->
<PathGeometry x:Key="geoPath">
<PathFigure StartPoint="0,0">
<LineSegment Point="10,0"/>
</PathFigure>
</PathGeometry>
</ResourceDictionary>
</Style.Resources>
</Style>
Upvotes: 0