我有一个WPF UserControl
- SegmentConrol
,它代表一条带有一些文字的行和一个显示方向的数组(>)。
由于我必须自定义这种控件样式,所以我决定切换到CustomControl,因为我认为这在某种程度上更好......
现在,我有一些“麻烦”从UC切换到CC。
特别是,不知道放置<UserControl.Resources>
部分的位置。
如果有任何专家建议我欢迎他们。
这是我的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,是新CustomControl的Themes/Generic.xaml
文件,我重构了旧的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>
如何处理代码
public SegmentControl()
{
this.line.StrokeDashCap = PenLineCap.Round;
this.arrow.StrokeLineJoin = PenLineJoin.Round;
this.Background = Brushes.Transparent;
}
未定义this.line
或this.arrow
时?感谢。
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;
}
答案 0 :(得分:6)
我不明白为什么你不能把它们直接放入资源词典?然后可以通过其他样式/模板重复使用它们。
<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">
<local:VisibilityConverter x:Key="VisibilityConverter"/>
<local:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
<local:SegmentToStringConverter x:Key="SegmentToStringConverter"/>
<Style....
修改强>
在回答第二个问题时,您需要在代码中执行此操作:
Line line = this.FindName("line") as Line;
Polygon arrow = this.FindName("arrow") as Polygon;
虽然通常的做法是使用“PART_”命名控件,使其显示为
Line line = this.FindName("PART_line") as Line;
Polygon arrow = this.FindName("PART_arrow") as Polygon;
此名称对应于xaml中给出的x:名称。
编辑3:
您需要确保您的窗口知道您的资源字典,如下所示:
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Namespace.Controls;component/Themes/CustomControls.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</WindowResources>
答案 1 :(得分:1)
另请注意,您必须添加
static SegmentControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(SegmentControl), new FrameworkPropertyMetadata(typeof(SegmentControl)));
}
到SegmentControl
以便应用默认主题而不直接指定样式。