【发布时间】:2020-02-14 10:20:10
【问题描述】:
我正在寻找一种将自定义控件的默认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,而且我已经有很多我使用的 TextBoxes 样式,所以我不想使用默认样式来应用模板:
<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 的构造函数/Init 例程中分配模板,但我正在努力从代码中获取资源字典;所以我想知道是否有更深奥的方法来做到这一点。
【问题讨论】:
-
您不能简单地将默认样式基于现有样式并设置
Template属性吗?<Style TargetType="{x:Type local:UnitTextBox}" BasedOn="{StaticResource RegularTextBox}">...</Style>。这种方法有什么问题? -
你可以,但是你必须将你拥有的 TextBox 样式的数量乘以 TextBox 衍生品的数量。由于我还有其他一些类似的案例,因此我预计这会在短期内造成混乱。这是我勉强的解决方案,但似乎应该有一些优雅的东西,对吧?
-
我不认为我理解这个问题。如果您想要不同于默认样式的其他样式,只需设置该特定元素的
Style属性。 “我希望有一些方法可以在 UnitTextBox 的构造函数/Init 例程中分配模板”。这有什么帮助? -
UnitTextBox 控件的核心功能(在 TextBox 中添加 TextBlock)绑定在默认样式中,如果我有 5 种不同的 TextBox 样式,在 UnitTextBox 上使用这些样式可以正常工作,除了它覆盖提供模板的默认样式。所以我必须明确分配模板,或者我必须根据 5 种样式中的每一种创建一个样式,为 Template 添加一个 setter 并使用它。它有效,但很糟糕。在初始化中设置模板意味着如果样式失败,它已经分配了模板。
-
您可以处理
Loaded并在事件处理程序中设置Template属性。
标签: .net wpf custom-controls desktop-application