2010-08-06 20 views
8

Jeśli mam dwa 200-liniowe szablony kontrolne, które różnią się tylko kilkoma słowami (kilka kolorów), w jaki sposób mogę dokonać ponownego użycia Xaml? Oznacza to, że nie trzeba kopiować i wklejać szablonu oraz zmieniać 3 słów w 200 liniach.Sparametryzowany styl/szablon w WPF?

Oto uproszczony przykład. Jedyna różnica między tymi dwoma stylami to kolor obramowania. Czy mogę w jakiś sposób zdefiniować ButtonStyle z sparametryzowanym kolorem i odziedziczyć z niego BlackButtonStyle i GrayButtonStyle i określić tylko ten kolor w BlackButtonStyle i GrayButtonStyle?

alt text http://img444.imageshack.us/img444/9545/buttonstyles.png

<Window x:Class="WpfApplication33.Window1" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="Window1" Height="300" Width="300"> 
    <Window.Resources> 

     <Style x:Key="BlackButtonStyle" TargetType="{x:Type Button}"> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate TargetType="{x:Type Button}"> 
         <Border BorderBrush="Black" BorderThickness="3"> 
          <ContentControl Content="{TemplateBinding Content}"/> 
         </Border> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 

     <Style x:Key="GrayButtonStyle" TargetType="{x:Type Button}"> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate TargetType="{x:Type Button}"> 
         <Border BorderBrush="Gray" BorderThickness="3"> 
          <ContentControl Content="{TemplateBinding Content}"/> 
         </Border> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 

    </Window.Resources> 
    <StackPanel> 
     <Button Content="Black Button" 
       Style="{StaticResource BlackButtonStyle}"/> 
     <Button Content="Gray Button" 
       Style="{StaticResource GrayButtonStyle}"/> 
    </StackPanel> 
</Window> 

Oto kod oparty na 2 odpowiedzi. styl musi jedynie być ustawiony na kontrolę, ale niestety nadal bałagan znacznika kontroli:

<Window x:Class="WpfApplication33.Window1" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="Window1" Height="300" Width="300"> 
    <Window.Resources> 

     <Style x:Key="ButtonStyle" TargetType="{x:Type Button}"> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate TargetType="{x:Type Button}"> 
         <Border Name="border" 
           BorderBrush="Black" 
           BorderThickness="3"> 
          <ContentControl Content="{TemplateBinding Content}"/> 
         </Border> 
         <ControlTemplate.Triggers> 
          <Trigger Property="Tag" Value="Gray"> 
           <Setter TargetName="border" 
             Property="BorderBrush" 
             Value="Gray"/> 
          </Trigger> 
         </ControlTemplate.Triggers> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 

     <Style x:Key="BlackButtonStyle" 
       TargetType="{x:Type Button}" 
       BasedOn="{StaticResource ButtonStyle}"/> 
     <Style x:Key="GrayButtonStyle" 
       TargetType="{x:Type Button}" 
       BasedOn="{StaticResource ButtonStyle}"> 
      <Setter Property="Tag" Value="Gray"/> 
     </Style> 

    </Window.Resources> 
    <StackPanel> 
     <Button Content="Black Button" 
       Style="{StaticResource BlackButtonStyle}"/> 
     <Button Content="Gray Button" 
       Style="{StaticResource GrayButtonStyle}"/> 
    </StackPanel> 
</Window> 

Odpowiedz

3

Prawo do zrobienia w tym jest zwykle do tworzenia DependencyProperty na klasie, która potrafi utrzymać sparametryzować dane, a następnie powiązać z tą właściwością w szablonie. Przez wzgląd na tworzenie szybki przykład, mam zamiar użyć właściwości Button.Tag, który działa doskonale do przechowywania coś tak prostego jak pędzlem:

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window1" Height="300" Width="300"> 
<Page.Resources> 
    <SolidColorBrush x:Key="BlackBrush" Color="Black"/> 
    <SolidColorBrush x:Key="GrayBrush" Color="Gray"/> 
    <Style x:Key="CustomButtonStyle" TargetType="{x:Type Button}"> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="{x:Type Button}"> 
        <Border BorderBrush="{TemplateBinding Tag}" BorderThickness="3"> 
         <ContentControl Content="{TemplateBinding Content}"/> 
        </Border> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</Page.Resources> 

<StackPanel> 
    <Button Content="Black Button" Tag="{StaticResource BlackBrush}" 
      Style="{StaticResource CustomButtonStyle}"/> 
    <Button Content="Gray Button" Tag="{StaticResource GrayBrush}" 
      Style="{StaticResource CustomButtonStyle}"/> 
</StackPanel> 

+0

Tak, też o tym myślałem, ale nie działa to w przypadku standardowych elementów sterujących, np. Przycisku, jeśli chcę uniknąć używania tagu. Będę musiał zmienić wszystkie moje przyciski na niestandardowe sterowanie. Dodatkowo wielokrotne określanie tej samej pary (tagu, stylu) jest nadal zduplikowanym kodem, ale o wiele mniej niż początkowo. –

+0

Można łatwo utworzyć kontrolkę UserControl, która hermetyzuje to wszystko i zapewnia DependencyProperty, aby ustawić kolor. Wtedy nie miałbyś powielonego kodu. Ale nie można uniknąć tworzenia oddzielnego elementu do przechowywania dodatkowych danych. – Charlie

4

Choć prawo Charliego o jego przykład, w twoim konkretnym przypadku użyłbym tylko właściwości BorderThickness i BorderBrush, które przycisk już pokazuje: możesz użyć {TemplateBinding BorderBrush} zamiast tworzyć własną własność.

Edit: Próbka XAML ... zauważ, że moje style domyślne znajduje się grubość kolor &, ale te mogą być zastąpione inline ...

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window1" Height="300" Width="300"> 
<Page.Resources> 
    <SolidColorBrush x:Key="BlackBrush" Color="Black"/> 
    <SolidColorBrush x:Key="GrayBrush" Color="Gray"/> 
    <Style x:Key="CustomButtonStyle" TargetType="{x:Type Button}"> 
     <Setter Property="BorderThickness" Value="3" /> 
     <Setter Property="BorderBrush" Value="{StaticResource BlackBrush}" /> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="{x:Type Button}"> 
        <Border BorderBrush="{TemplateBinding BorderBrush}" BorderColor="{TemplateBinding BorderThickness}"> 
         <ContentControl Content="{TemplateBinding Content}"/> 
        </Border> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</Page.Resources> 

<StackPanel> 
    <Button Content="Black Button" BorderBrush="{StaticResource BlackBrush}" 
      Style="{StaticResource CustomButtonStyle}"/> 
    <Button Content="Gray Button" BorderBrush="{StaticResource GrayBrush}" 
      Style="{StaticResource CustomButtonStyle}"/> 
</StackPanel> 
+0

Mam problem z wizualizacją tego, mimo że * brzmi * jak najlepsze rozwiązanie w tym przypadku. Czy możesz wyjaśnić, jak to wyglądałoby w kodzie? – Berryl

+0

@Berryl: zobacz moją edycję. To niewiele różni się od Charliego, używam tylko właściwości, które już tam są. Zwróć uwagę w szczególności, że możesz zdefiniować domyślny styl, w którym wszystkie przyciski będą się podnosić. –

+0

Tak, fajne. Zaznaczę to jako odpowiedź, jeśli to było moje pytanie! Twoje zdrowie – Berryl

2

Wystarczy popatrzeć na this solution, to rozwiązuje problem dokładnego you” ponownie mieć.