I have a WPF UserControl
- SegmentConrol
, that represents a line with some text and an array displaying the direction (>).
As I have to customize this control styles, I decided to switch to a CustomControl, because I read this is better in a way...
Now, I have some "troubles" to switch from UC to CC.
Particularly, no idea where to put the <UserControl.Resources>
part.
If any of experts could advise me they are welcomed.
Here is my UserControl:
<UserControl x:Class="MyNamespace.ctlWpfPlanDeLigne.SegmentControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
xmlns:local="clr-namespace:MyNamespace.ctlWpfPlanDeLigne"
d:DesignHeight="300" d:DesignWidth="300"
x:Name="ParentSegmentControl">
<UserControl.Resources>
<local:VisibilityConverter x:Key="VisibilityConverter"/>
<local:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
<local:SegmentToStringConverter x:Key="SegmentToStringConverter"/>
</UserControl.Resources>
<Canvas Background="Transparent">
<Line x:Name="line"
X1="{Binding ElementName=ParentSegmentControl, Path=X1}"
Y1="{Binding ElementName=ParentSegmentControl, Path=Y1}"
X2="{Binding ElementName=ParentSegmentControl, Path=X2}"
Y2="{Binding ElementName=ParentSegmentControl, Path=Y2}" IsHitTestVisible="True"/>
<Label x:Name="label"
Foreground="{Binding ElementName=ParentSegmentControl, Path=LabelForeground}"
Background="{Binding ElementName=ParentSegmentControl, Path=LabelBackground}"
Visibility="{Binding ElementName=ParentSegmentControl, Path=IsLabelUsed, Converter={StaticResource BoolToVisibilityConverter}}"
>
<Label.Effect>
<DropShadowEffect BlurRadius="2" Color="White" Opacity="1" RenderingBias="Performance" ShadowDepth="0" />
</Label.Effect>
</Label>
<Polygon Name="arrow" Visibility="{Binding ElementName=ParentSegmentControl, Path=IsArrowUsed, Converter={StaticResource BoolToVisibilityConverter}}"/>
</Canvas>
</UserControl>
Bellow, is the Themes/Generic.xaml
file of the new CustomControl I refactor the old UserControl:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyNamespace.ctlWpfPlanDeLigne">
<Style TargetType="{x:Type local:SegmentControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:SegmentControl}">
<Canvas Background="Transparent">
<Line x:Name="line"...
<Label x:Name="label"...
<Polygon x:Name="arrow" ...
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Edit:
What to do with the code
public SegmentControl()
{
this.line.StrokeDashCap = PenLineCap.Round;
this.arrow.StrokeLineJoin = PenLineJoin.Round;
this.Background = Brushes.Transparent;
}
when this.line
or this.arrow
is not defined? Thanks.
EDIT 2
Generic.XAML:
<Style TargetType="{x:Type local:SegmentControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:SegmentControl}">
<Canvas Background="Transparent">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
</Border>
<Line x:Name="PART_line"
X1="{Binding ElementName=ParentSegmentControl, Path=X1}"
Y1="{Binding ElementName=ParentSegmentControl, Path=Y1}"
X2="{Binding ElementName=ParentSegmentControl, Path=X2}"
Y2="{Binding ElementName=ParentSegmentControl, Path=Y2}"
IsHitTestVisible="True"/>
<Label x:Name="PART_label"
Foreground="{Binding ElementName=ParentSegmentControl, Path=LabelForeground}"
Background="{Binding ElementName=ParentSegmentControl, Path=LabelBackground}"
Visibility="{Binding ElementName=ParentSegmentControl, Path=IsLabelUsed, Converter={StaticResource BoolToVisibilityConverter}}">
<Label.Effect>
<DropShadowEffect BlurRadius="2" Color="White" Opacity="1" RenderingBias="Performance" ShadowDepth="0" />
</Label.Effect>
</Label>
<Polygon x:Name="PART_arrow"
Visibility="{Binding ElementName=ParentSegmentControl, Path=IsArrowUsed, Converter={StaticResource BoolToVisibilityConverter}}"/>
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
.cs:
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
this.line = this.FindName("PART_line") as Line; // null
this.arrow = this.FindName("PART_arrow") as Polygon; // null
this.label = this.FindName("PART_label") as Label; // null
this.line.StrokeDashCap = PenLineCap.Round;
this.arrow.StrokeLineJoin = PenLineJoin.Round;
}
Also note that you have to add
to
SegmentControl
in order to apply the default theme without specifying the style directly.I don't see why you can't just put them straight into the resource dictionary? They can then be re-used by other styles/templates..
EDIT:
In response to your second question, you will need to do this in code:
Although it's common practice to name your controls with "PART_" so it reads
This name corresponds to the x:Name given in the xaml..
EDIT 3:
You'll need to make sure your window knows about your resource dictionary like this: