在不使用样式的情况下设置自定义控件的默认控件模板
Set the default Control Template of a Custom Control without using a Style
我正在寻找一种方法来将自定义控件的默认值 Control Template
更牢固地绑定到该控件,而不是使用 Style
。我将在这里展示我最简单的例子来解释需求:
public class UnitTextBox : TextBox
{
public string UnitLabel {...}
public static readonly DependencyProperty UnitLabelProperty =
DependencyProperty.Register("UnitLabel", typeof(string), typeof(UnitTextBox), new PropertyMetadata(""));
}
此控件只是为单位标签(如毫米)添加了一个额外的字符串 属性,给定以下派生自 TextBox
的简单控件模板,它将单位标签放在文本框中以保持物品美观、干净且尺寸合适:
<ControlTemplate x:Key="UnitTextBoxTemplate" TargetType="{x:Type local:UnitTextBox}">
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<DockPanel>
<TextBlock DockPanel.Dock="Right" Text="{TemplateBinding UnitLabel}" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="8,0,2,0" Focusable="False" IsHitTestVisible="False" Background="Transparent" Foreground="{TemplateBinding Foreground}"
FontSize="{TemplateBinding FontSize}" FontStyle="{TemplateBinding FontStyle}" />
<ScrollViewer x:Name="PART_ContentHost" Focusable="False" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
</DockPanel>
</Border>
...(triggers)
</ControlTemplate>
所有这些都非常有效,但是这个控件基本上仍然是一个 TextBox
,而且我已经使用了很多用于文本框的样式,所以我不想使用默认样式来应用模板:
<Style TargetType="{x:Type local:UnitTextBox}">
<Setter Property="Template" Value="{DynamicResource UnitTextBoxTemplate}"/>
</Style>
执行上述操作意味着我无法使用我的 RegularTextBox
风格,它非常适合我的 UnitTextBox
。因此,每次我想添加 UnitTextBox
时,我都必须明确指定使其正常运行的模板:
<ctrl:UnitTextBox Template="{DynamicResource UnitTextBoxTemplate}" UnitLabel="mm/min"
Style="{StaticResource RegularTextBox}"/>
我使用 WPF 已经有很长时间了,但我做的自定义控件相对较少,并且当我使用它们时使用默认样式方法时遇到了问题,但我认为 必须 是一个更好的方法,但是 google-fu 一次又一次地让我失望。
我希望有一些方法可以在 UnitTextBox
的 constructor/Init 例程中分配模板,但我正在努力从代码中获取资源字典;所以我想知道是否有更深奥的方法来做到这一点。
如果您不想定义默认值 Style
,您可以在控件 class 中处理 Loaded
事件并设置 Template
属性 在事件处理程序中。
public UnitTextBox() : base()
{
this.Loaded += UnitTextBox_Loaded;
}
private void UnitTextBox_Loaded(object sender, RoutedEventArgs e)
{
var res = this.FindResource("UnitTextBoxTemplate");
this.Template = res as ControlTemplate;
}
我正在寻找一种方法来将自定义控件的默认值 Control Template
更牢固地绑定到该控件,而不是使用 Style
。我将在这里展示我最简单的例子来解释需求:
public class UnitTextBox : TextBox
{
public string UnitLabel {...}
public static readonly DependencyProperty UnitLabelProperty =
DependencyProperty.Register("UnitLabel", typeof(string), typeof(UnitTextBox), new PropertyMetadata(""));
}
此控件只是为单位标签(如毫米)添加了一个额外的字符串 属性,给定以下派生自 TextBox
的简单控件模板,它将单位标签放在文本框中以保持物品美观、干净且尺寸合适:
<ControlTemplate x:Key="UnitTextBoxTemplate" TargetType="{x:Type local:UnitTextBox}">
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<DockPanel>
<TextBlock DockPanel.Dock="Right" Text="{TemplateBinding UnitLabel}" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="8,0,2,0" Focusable="False" IsHitTestVisible="False" Background="Transparent" Foreground="{TemplateBinding Foreground}"
FontSize="{TemplateBinding FontSize}" FontStyle="{TemplateBinding FontStyle}" />
<ScrollViewer x:Name="PART_ContentHost" Focusable="False" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
</DockPanel>
</Border>
...(triggers)
</ControlTemplate>
所有这些都非常有效,但是这个控件基本上仍然是一个 TextBox
,而且我已经使用了很多用于文本框的样式,所以我不想使用默认样式来应用模板:
<Style TargetType="{x:Type local:UnitTextBox}">
<Setter Property="Template" Value="{DynamicResource UnitTextBoxTemplate}"/>
</Style>
执行上述操作意味着我无法使用我的 RegularTextBox
风格,它非常适合我的 UnitTextBox
。因此,每次我想添加 UnitTextBox
时,我都必须明确指定使其正常运行的模板:
<ctrl:UnitTextBox Template="{DynamicResource UnitTextBoxTemplate}" UnitLabel="mm/min"
Style="{StaticResource RegularTextBox}"/>
我使用 WPF 已经有很长时间了,但我做的自定义控件相对较少,并且当我使用它们时使用默认样式方法时遇到了问题,但我认为 必须 是一个更好的方法,但是 google-fu 一次又一次地让我失望。
我希望有一些方法可以在 UnitTextBox
的 constructor/Init 例程中分配模板,但我正在努力从代码中获取资源字典;所以我想知道是否有更深奥的方法来做到这一点。
如果您不想定义默认值 Style
,您可以在控件 class 中处理 Loaded
事件并设置 Template
属性 在事件处理程序中。
public UnitTextBox() : base()
{
this.Loaded += UnitTextBox_Loaded;
}
private void UnitTextBox_Loaded(object sender, RoutedEventArgs e)
{
var res = this.FindResource("UnitTextBoxTemplate");
this.Template = res as ControlTemplate;
}