2013-01-24 13 views
10

私はのStackPanelの子である特定のタイプのコントロールのスタイルを設定する必要がWPFのControlTemplateは、スタイルに

を働くんものを壊します。私は使用しています:

<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> 

方法はあります - そのControlTemplateの内部のTextBlockが定義されたスタイルを見つけるために作る - ControlTemplate.ResourcesにStackPanel.Resourcesでスタイルを複製する以外に? WPFはboundryをするControlTemplatesを考慮し、テンプレートの内側(x:Keyなしスタイル)暗黙のスタイルを適用しません

答えて

21

おかげで...。

ただし、このルールには例外が1つあります。Controlから継承するものは暗黙のスタイルを適用します。

だからではなくTextBlockLabelを使用することができ、そしてそれはあなたのXAMLの階層まで、さらに定義された暗黙的なスタイルを適用する、しかしFrameworkElement代わりのControlからTextBlock継承しているので、それは自動的に暗黙のスタイルを適用していないし、あなた手動で追加する必要があります。

これを回避するために私の最も一般的な方法は、既存の暗黙のTextBlockスタイルにこの歩き回るの

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

他の一般的な方法をBasedOnあるControlTemplate.Resourcesで暗黙的なスタイルを追加することですが、次のとおりです。

  • 暗黙のスタイルを<Application.Resources>に配置します。テンプレートの境界にかかわらず、ここに配置されたスタイルはアプリケーション全体に適用されます。それはボタンやコンボボックス

    <Application.Resources> 
        <Style TargetType="{x:Type TextBlock}"> 
         <Setter Property="Foreground" Value="Green" /> 
        </Style> 
    </Application.Resources> 
    
  • 利用代わりにそれがControlから継承されていますので、TextBlockLabelのように、同様に他のコントロールの内部でTextBlocksにスタイルを適用するように、しかしこれには注意してください、そう暗黙的に適用されます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にスタイルを適用する方法を理解しました。 3番目の例は照明で、私が必要とするControlTemplateだけにスタイルを適用することができます。 –