2010-08-06 29 views
8

Nếu tôi có hai mẫu kiểm soát dài 200 dòng chỉ khác nhau trong một vài từ (một vài màu), làm cách nào để tôi có thể sử dụng lại xaml? Tức là, không phải sao chép-dán mẫu và thay đổi 3 từ trong 200 dòng.Kiểu/mẫu tham số trong WPF?

Dưới đây là một ví dụ đơn giản. Sự khác biệt duy nhất giữa hai kiểu là màu đường viền. Vì vậy, tôi có thể bằng cách nào đó xác định một ButtonStyle, với một màu tham số, và kế thừa BlackButtonStyle và GrayButtonStyle từ nó, và chỉ định màu sắc đó trong BlackButtonStyle và 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> 

Đây là mã dựa trên 2 câu trả lời. Chỉ có một phong cách cần phải được đặt trên sự kiểm soát, nhưng tiếc là nó vẫn messes lên Tag của điều khiển:

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

Trả lời

3

Cách đúng để đi về điều này thường là để tạo ra một DependencyProperty trên lớp mà có thể giữ dữ liệu được parametrized và sau đó liên kết với thuộc tính đó trong mẫu của bạn. Vì lợi ích của việc tạo ra một ví dụ nhanh, tôi sẽ sử dụng Button.Tag bất động sản, hoạt động hoàn toàn tốt để lưu trữ một cái gì đó đơn giản như một bàn chải:

<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

Vâng, tôi cũng nghĩ về điều này, nhưng nó không hoạt động đối với các điều khiển tiêu chuẩn, tức là Nút, nếu tôi muốn tránh sử dụng Thẻ. Tôi sẽ cần phải thay đổi tất cả các nút của tôi thành một điều khiển tùy chỉnh. Cộng với việc chỉ định cùng một cặp (thẻ, kiểu) nhiều lần vẫn là mã trùng lặp, nhưng ít hơn rất nhiều so với ban đầu. –

+0

Bạn có thể dễ dàng tạo ra một UserControl bao gồm tất cả điều này và cung cấp một DependencyProperty để thiết lập màu sắc. Sau đó, bạn sẽ không có mã trùng lặp. Nhưng bạn không thể tránh tạo ra một loại thực thể riêng biệt để lưu trữ dữ liệu bổ sung. – Charlie

4

Trong khi đúng Charlie về ví dụ của mình, cho trường hợp cụ thể của bạn, tôi chỉ sử dụng các thuộc tính BorderThicknessBorderBrush mà nút đã hiển thị: bạn có thể sử dụng {TemplateBinding BorderBrush} thay vì tạo thuộc tính của riêng bạn.

Edit: mẫu XAML ... lưu ý rằng giá trị mặc định phong cách của tôi dày màu &, nhưng những thể được ghi đè 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

Tôi gặp sự cố khi trực quan hóa hình ảnh này mặc dù âm thanh * giống như giải pháp tốt nhất trong trường hợp này. Bạn có thể trình bày cách mã này trông như thế nào không? – Berryl

+0

@Berryl: xem chỉnh sửa của tôi. Nó không có nhiều khác biệt so với Charlie, tôi chỉ sử dụng những đặc tính đã có ở đó. Lưu ý đặc biệt là bạn có thể xác định mặc định theo kiểu mà tất cả các nút sẽ nhận. –

+0

Vâng, tuyệt. Tôi đánh dấu đây là câu trả lời nếu đó là câu hỏi của tôi! Chúc mừng – Berryl

2

Có một cái nhìn tại this solution, nó giải quyết vấn đề chính xác mà bạn' đang có.