Dot-Net

WPF ControlTemplates 是否必須有 TargetType?

  • August 6, 2020

WPF 中的 ControlTemplates 是否需要 TargetType?我正在重新設置一些控制項的樣式,並註意到 comboboxitem、listiviewitem 和 listboxitem 都具有相同的模板:

   <ControlTemplate x:Key="ListBoxItemCT" TargetType="{x:Type ListBoxItem}">

   <Border x:Name="Bd" 
       SnapsToDevicePixels="true" 
       Background="{TemplateBinding Background}" 
       BorderBrush="{TemplateBinding BorderBrush}" 
       BorderThickness="{TemplateBinding BorderThickness}" 
       Padding="{TemplateBinding Padding}"
       CornerRadius="1">
       <ContentPresenter x:Name="cpItemContent"
           HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
           VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
           SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
           />
   </Border>

</ControlTemplate>

是否可以只刪除 TargetType 並為所有三個模板提供一個模板?我正在嘗試這樣做,但會遇到奇怪的錯誤和問題。我找不到 ControlTemplates 必須具有類型的任何特定參考。

對 TargetType 沒有要求,但如果您不指定一個,它的行為將與您指定 Control 的 TargetType 相同。

  • 指定類型的主要優點是可以訪問該類型的所有依賴屬性,例如 TemplateBindings 和 Triggers,而無需使用所有者類型限定屬性。
  • 如果沒有 TargetType,您也可能會失去隱式綁定,例如 ContentPresenter 到 ContentControl.Content 屬性。

一旦您指定了 TargetType,該模板只能應用於該類型的控制項或從該類型派生的控制項。要在不同類型之間共享,只需指定一個公共基類 - 在這種情況下為 ContentControl。

以下簡單模板將給出相同的基本結果,但第一個更可取且更常見:

<ControlTemplate x:Key="CommonContentTemplate" TargetType="{x:Type ContentControl}">
   <Border x:Name="Bd" 
           SnapsToDevicePixels="true" 
           Background="{TemplateBinding Background}" 
           BorderBrush="{TemplateBinding BorderBrush}"
           BorderThickness="{TemplateBinding BorderThickness}" 
           Padding="{TemplateBinding Padding}"
           CornerRadius="1">
       <ContentPresenter x:Name="cpItemContent"
                         HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                         VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
                         SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
   </Border>
</ControlTemplate>

如果沒有類型,所有 Content 屬性都需要手動連接:

<ControlTemplate x:Key="CommonTemplate">
   <Border x:Name="Bd" 
           SnapsToDevicePixels="true" 
           Background="{TemplateBinding Background}" 
           BorderBrush="{TemplateBinding BorderBrush}"
           BorderThickness="{TemplateBinding BorderThickness}" 
           Padding="{TemplateBinding Padding}"
           CornerRadius="1">
       <ContentPresenter x:Name="cpItemContent"
                         HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                         VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
                         SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                         Content="{TemplateBinding ContentControl.Content}"
                         ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}"
                         ContentTemplateSelector="{TemplateBinding ContentControl.ContentTemplateSelector}"
                         ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}"/>
   </Border>
</ControlTemplate>

為了完整起見,請注意文件說明了這一點:

如果模板定義包含 ContentPresenter,則 ControlTemplate需要TargetType 屬性。

儘管它沒有對此要求進行解釋,但很可能是John Bowen 的答案給出的推理,即您必須手動指定基本屬性Content,否則會自動連接。

引用自:https://stackoverflow.com/questions/3632181