2013-01-24 134 views
10

,它工作WPF控件模板打破風格

我需要的風格,是一個StackPanel的兒童某一類型的控制的東西。我正在使用:

<StackPanel> 
    <StackPanel.Resources> 
     <Style TargetType="{x:Type TextBlock}">...</Style> 
    </StackPanel.Resources> 
    <TextBlock ...> 
    ... 
</StackPanel> 

而且這工作正常!每個TextBlock都會查看其父級(StackPanel)的資源,以瞭解應該如何設置樣式。無論您將TextBlock嵌套到StackPanel下方多遠,如果它沒有在其直接父級中找到樣式,它將查看其父級的父級等等,直到它找到某種東西(在這種情況下,在中定義的樣式)。

不起作用

我遇到了一個問題,當我嵌套在ContentControl中,其中有一個模板裏面TextBlock中的東西(見下面的代碼)。 ControlTemplate似乎破壞了TextBlock從其父母,祖父母等人獲取其風格的方式...

ControlTemplate的使用似乎有效地消除了TextBlock找到合適風格的方式(StackPanel中的風格)。參考資料)。當它遇到ControlTemplate時,它會停止在樹上的資源中查找它的樣式,而是默認使用應用程序本身的MergedDictionaries中的樣式。

<StackPanel Orientation="Vertical" Background="LightGray"> 
    <StackPanel.Resources> 
     <Style TargetType="{x:Type TextBlock}"> 
      <Setter Property="Foreground" Value="Green" /> 
     </Style> 
    </StackPanel.Resources> 

    <TextBlock Text="plain and simple in stackpanel, green" /> 
    <ContentControl> 
     <TextBlock Text="inside ContentControl, still green" /> 
    </ContentControl> 
    <ContentControl> 
     <ContentControl.Template> 
      <ControlTemplate TargetType="{x:Type ContentControl}"> 
       <StackPanel Orientation="Vertical"> 
        <ContentPresenter /> 
        <TextBlock Text="how come this one - placed in the template - is not green?" /> 
       </StackPanel> 
      </ControlTemplate> 
     </ContentControl.Template> 
     <TextBlock Text="inside ContentControl with a template, this one is green as well" /> 
    </ContentControl> 

</StackPanel> 

是否有辦法 - 除了在StackPanel.Resources複製樣式到ControlTemplate.Resources - 使該控件模板裏面TextBlock中找到定義的樣式?

謝謝...

回答

21

WPF認爲ControlTemplates是一個boundry,和(無x:Key樣式)的模板內將不適用含蓄的風格。

但是這個規則有一個例外:從Control繼承的任何東西都會應用隱式樣式。

所以,你可以使用一個Label代替TextBlock,它會從FrameworkElement,而不是Control適用你的XAML層次進一步明確了含蓄的風格,但是因爲TextBlock繼承,它不會自動應用隱含的風格和你必須手動添加它。

我最常用的方式來解決這個問題是在ControlTemplate.ResourcesBasedOn現有隱含TextBlock風格解決此獲得的

<ControlTemplate.Resources> 
     <Style TargetType="{x:Type TextBlock}" 
       BasedOn="{StaticResource {x:Type TextBlock}}" /> 
    <ControlTemplate.Resources> 

其他常見的方法來添加一個隱含的風格是:

  • 將隱式樣式放在<Application.Resources>中。放置在這裏的樣式將適用於整個應用程序,而不管模板邊界如何。小心這雖然,因爲這將樣式應用到TextBlocks其他控件的內部,以及像按鈕或組合框

    <Application.Resources> 
        <Style TargetType="{x:Type TextBlock}"> 
         <Setter Property="Foreground" Value="Green" /> 
        </Style> 
    </Application.Resources> 
    
  • 使用Label而不是TextBlock,因爲它是從Control繼承的,因此將適用隱在ControlTemplate

  • 之外定義樣式給基風格的x:Key,並以此爲基本樣式爲ControlTemplate內隱式TextBlock風格。這幾乎是一樣的頂級解決方案,但是它的使用有一個x:Key屬性

    <Style x:Key="BaseTextBlockStyle" TargetType="{x:Type TextBlock}"> 
        <Setter Property="Foreground" Value="Green" /> 
    </Style> 
    
    ... 
    
    <ControlTemplate.Resources> 
        <Style TargetType="{x:Type TextBlock}" 
         BasedOn="{StaticResource BaseTextBlockStyle}" /> 
    <ControlTemplate.Resources> 
    
+0

很好的解釋基本樣式!我也喜歡你使用BasedOn =「{StaticResource {x:Type TextBlock}}」的方式。有趣。現在我知道WPF認爲ControlTemplates是一個邊界,我可以嘗試解決它:) –

+0

謝謝,我終於明白如何將樣式應用於我的ControlTemplate。第三個例子是照亮,並允許我只將樣式應用到我需要的ControlTemplate(s)。 –