WPF 控件模板:为什么在显而易见的地方需要 TargetType?

WPF control template : why TargetType is required where its obvious?

我对wpf中xaml的过度冗长感到有点困惑。例如在定义控件模板时,您仍然必须将目标类型指定为控件本身。是否需要指定 TargetType?因为我正在定义 TargetControl 的模板元素,所以在未指定时它不会默认为 TargetControl 吗?

<local:TargetControl Width="100" Height="100">
 <local:TargetControl.Template>
    <ControlTemplate TargetType="local:TargetControl">
      <Grid>
        <Ellipse x:Name="PART_Target" Fill="Blue" />
      <Grid>
    </ControlTemplate>
 </local:TargetControl.Template>
</local:TargetControl>

标记 <ControlTemplate> </ControlTemplate> 表示使用默认构造函数 (new ControlTemplate()) 创建新的 ControlTemplate 实例。构造函数不知道哪个元素将使用模板。

在这个例子中

<ControlTemplate TargetType="local:TargetControl">
  <Grid>
    <Ellipse x:Name="PART_Target" Fill="Blue" />
  <Grid>
</ControlTemplate>

模板可以在没有 TargetType 的情况下使用,因为它不使用 TemplateBinding 的任何 TargetControl 特定属性。如果需要 TemplateBindings,还必须设置 TargetType。

在大多数情况下,元素模板具有与元素类型相同的 TargetType。

但也可能存在特殊情况,例如:我希望我的 RadioButtons 和 CheckBoxes 看起来像彩色圆圈 - 选中时为绿色,未选中时为灰色。

RadioButton 和 CheckBox 派生自 ToggleButton,因此我为 ToggleButton 创建模板并应用于我的 RadioButton 和 CheckBox:

<StackPanel>
    <StackPanel.Resources>
        <ControlTemplate TargetType="{x:Type ToggleButton}" x:Key="Toggle">
            <Border Name="btn" BorderBrush="Black" Background="Gainsboro"
                    Width="28" Height="28" CornerRadius="14" />

            <ControlTemplate.Triggers>
                <Trigger Property="IsChecked" Value="True">
                    <Setter Property="Background" TargetName="btn" Value="Lime" />
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </StackPanel.Resources>

    <CheckBox Template="{StaticResource Toggle}" />
    <RadioButton Template="{StaticResource Toggle}" />
    <RadioButton Template="{StaticResource Toggle}"  />
</StackPanel>

这个例子还演示了当ControlTemplate在资源字典中定义时没有连接到特定元素的情况,因此无法推断出TargetType。

所以至少有 3 种情况下 TargetType 不确定或不需要。所以留给开发人员始终提供具体类型