2013-01-24 23 views
10

rzeczy, które działaWPF ControlTemplate łamie stylem

muszę projektować kontrole pewnego rodzaju, że jesteśmy dziećmi StackPanel. Używam:

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

To działa dobrze! Każdy obiekt TextBlock sprawdza zasoby swojego rodzica (StackPanel), aby dowiedzieć się, jak powinien wyglądać styl. Nie ma znaczenia, jak głęboko zagnieżdżasz TextBlock w dół StackPanel ... jeśli nie znajdzie stylu w swoim bezpośrednim rodzicu, to spojrzy na rodzica rodzica i tak dalej, aż znajdzie coś (w tym przypadku , styl, który został zdefiniowany w).

Rzeczy, które nie działa

wpadłem na problem, kiedy zagnieżdżone TextBlock wewnątrz ContentControl, który miał szablonu (patrz kod poniżej). ControlTemplate wydaje się zakłócać sposób, w jaki TextBlock odzyskuje swój styl od swoich rodziców, dziadków, ...

Efektywne wykorzystanie ControlTemplate wydaje się przełamać na zimno sposób znalezienia przez TextBlock właściwego stylu (ten w StackPanel. Zasoby). Po napotkaniu ControlTemplate przestaje wyszukiwać swój styl w zasobach znajdujących się w drzewie, a zamiast tego domyślnie wybiera styl w MergedDictionaries samej aplikacji.

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

Czy istnieje sposób - oprócz powielenie stylu w StackPanel.Resources do ControlTemplate.Resources - aby TextBlock wewnątrz tego ControlTemplate znaleźć określony styl?

Dzięki ...

Odpowiedz

21

WPF uważa ControlTemplates się być boundry i nie będzie stosować style niejawne (style bez x:Key) wewnątrz szablonów.

Ale istnieje jeden wyjątek od tej reguły: wszystko, co dziedziczy po Control, zastosuje style niejawne.

Więc można użyć Label zamiast TextBlock, i byłoby zastosować styl niejawny zdefiniowaną dalej w górę hierarchii XAML, jednak od TextBlock dziedziczy FrameworkElement zamiast Control, że nie będzie stosować się niejawny styl automatycznie i trzeba dodać ręcznie.

Moim najczęstszym sposobem poruszania się po to, aby dodać niejawny styl w ControlTemplate.Resources że jest BasedOn tej instalacji niejawna TextBlock stylem

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

innych wspólnych sposobów poruszania tego są:

  • Umieść domyślny styl w <Application.Resources>. Style umieszczone tutaj będą miały zastosowanie do całej aplikacji, niezależnie od granic szablonów.Bądź ostrożny z tym jednak, jak to zastosować styl do TextBlocks wewnątrz innych elementów, a także, jak przyciski czy comboboxes

    <Application.Resources> 
        <Style TargetType="{x:Type TextBlock}"> 
         <Setter Property="Foreground" Value="Green" /> 
        </Style> 
    </Application.Resources> 
    
  • użyć Label zamiast TextBlock ponieważ jest dziedziczone z Control, więc będzie miała zastosowanie niejawny style zdefiniowane poza ControlTemplate

  • Daj styl bazowy x:Key i używać go jako podstawy dla stylu niejawna TextBlock stylów wewnątrz ControlTemplate. To niemal tak samo jak najlepszym rozwiązaniem, jednak jest on wykorzystywany do stylów bazowych, które mają atrybut 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

Wielki wyjaśnienie! Podoba mi się również sposób, w jaki używasz BasedOn = "{StaticResource {x: Type TextBlock}}". Ciekawy. A teraz wiem, że WPF uważa ControlTemplates za granicę, mogę spróbować obejść to :) –

+0

Dzięki, w końcu zrozumiałem, jak zastosować styl do mojego ControlTemplate. Trzecim przykładem było podświetlanie i pozwala mi zastosować styl tylko do ControlTemplate (s), których potrzebuję. –

Powiązane problemy