2012-02-10 150 views
20

我有一個標準樣式的按鈕,但我希​​望樣式的某些部分是可配置的。例如MouseOver觸發按鈕時我出現邊框,我希望邊框顏色可以配置。模板綁定與附加屬性

以下這篇文章:http://www.thomaslevesque.com/2011/10/01/wpf-creating-parameterized-styles-with-attached-properties/我想我可以使用附加的屬性和TemplateBinding來實現這一點。

我創建了以下附加屬性:

public static class ThemeProperties 
{ 
    public static Brush GetButtonBorderColour(DependencyObject obj) 
    { 
     return (Brush)obj.GetValue(ButtonBorderColourProperty); 
    } 

    public static void SetButtonBorderColour(DependencyObject obj, Brush value) 
    { 
     obj.SetValue(ButtonBorderColourProperty, value); 
    } 

    public static readonly DependencyProperty ButtonBorderColourProperty = 
     DependencyProperty.RegisterAttached(
      "ButtonBorderColour", 
      typeof(Brush), 
      typeof(ThemeProperties), 
      new FrameworkPropertyMetadata(Brushes.Black, FrameworkPropertyMetadataOptions.Inherits)); 
} 

我設置像這樣的屬性:

<Button Style="{StaticResource RedButton}" local:ThemeProperties.ButtonBorderColour="#B20000"/> 

而且我的風格是這樣的:

<Window.Resources> 
    <Style x:Key="RedButton" TargetType="Button"> 
     <Setter Property="OverridesDefaultStyle" Value="True"/> 
     <Setter Property="Margin" Value="2"/> 
     <Setter Property="FontFamily" Value="Tahoma"/> 
     <Setter Property="FontSize" Value="11px"/> 
     <Setter Property="FontWeight" Value="Bold"/> 
     <Setter Property="Foreground" Value="White"/> 
     <Setter Property="MinHeight" Value="25" /> 

     <Setter Property="FocusVisualStyle" Value="{StaticResource MyFocusVisual}" /> 
     <Setter Property="Background" > 
      <Setter.Value> 
       <LinearGradientBrush StartPoint="0,0" EndPoint="0,1" > 
        <GradientStop Color="#FECCBF" Offset="0.2"/> 
        <GradientStop Color="Red" Offset="0.85"/> 
        <GradientStop Color="#FECCBF" Offset="1"/> 
       </LinearGradientBrush> 
      </Setter.Value> 
     </Setter> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="Button"> 
        <Border Name="border" BorderThickness="1" Padding="4,2" BorderBrush="Transparent" CornerRadius="3" Background="{TemplateBinding Background}"> 
         <Grid > 
          <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Name="content"/> 
         </Grid> 
        </Border> 
        <ControlTemplate.Triggers> 
         <Trigger Property="IsMouseOver" Value="True"> 
          <Setter TargetName="border" Property="BorderBrush" Value="{TemplateBinding local:ThemeProperties.ButtonBorderColour}" /> 
          <Setter Property="Foreground" Value="#B20000" /> 
         </Trigger> 
         <Trigger Property="IsPressed" Value="True"> 
          <Setter Property="Background" > 
           <Setter.Value> 
            <LinearGradientBrush StartPoint="0,0" EndPoint="0,1" > 
             <GradientStop Color="#FECCBF" Offset="0.35"/> 
             <GradientStop Color="Red" Offset="0.95"/> 
             <GradientStop Color="#FECCBF" Offset="1"/> 
            </LinearGradientBrush> 
           </Setter.Value> 
          </Setter> 
          <Setter TargetName="content" Property="RenderTransform" > 
           <Setter.Value> 
            <TranslateTransform Y="1.0" /> 
           </Setter.Value> 
          </Setter> 
         </Trigger> 
         <Trigger Property="IsDefaulted" Value="True"> 
          <Setter TargetName="border" Property="BorderBrush" Value="#B20000" /> 
         </Trigger> 
         <Trigger Property="IsFocused" Value="True"> 
          <Setter TargetName="border" Property="BorderBrush" Value="#B20000" /> 
         </Trigger> 
         <Trigger Property="IsEnabled" Value="False"> 
          <Setter TargetName="border" Property="Opacity" Value="0.7" /> 
          <Setter Property="Foreground" Value="Gray" /> 
         </Trigger> 
        </ControlTemplate.Triggers> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</Window.Resources> 

凡重點線是

<Trigger Property="IsMouseOver" Value="True"> 
    <Setter TargetName="border" Property="BorderBrush" Value="{TemplateBinding local:ThemeProperties.ButtonBorderColour}" /> 
    <Setter Property="Foreground" Value="#B20000" /> 
</Trigger> 

至於我可以看到這個應該工作,但我在運行時獲得上述線以下錯誤:

「值」不能轉換價值屬性類型的'對象。 標記文件中對象'System.Windows.Setter'的錯誤

我在這裏做了一些不正確的事嗎?我是WPF全新的,並且無法確定發生了什麼問題,因爲附加屬性的類型是Brush,這是我期望Border的BorderBrush屬性需要的。

回答

39

我認爲TemplateBinding是在編譯時計算的,因此您不能在Setter中動態設置TemplateBinding,請嘗試使用Binding(請參閱下文)。

<Setter TargetName="border" Property="BorderBrush" 
     Value="{Binding Path=(local:ThemeProperties.ButtonBorderColour), 
         RelativeSource={RelativeSource TemplatedParent}}"/> 

希望這會有所幫助。

+0

嘿我編輯了我的答案,它現在應該工作。這是一個語法錯誤,對此感到遺憾。 – 2012-02-10 22:34:19

+0

謝謝小川,那已經很完美了。我還可以看到我的代碼和鏈接網頁上的示例之間的區別,因爲示例沒有在以前不讚賞的setter中使用TemplateBinding。再次感謝! – thudbutt 2012-02-13 10:14:08

+0

我不明白爲什麼我的相同案件在設計時不起作用(但它在運行時) - http://stackoverflow.com/questions/41614676/binding-style-property-value-to-an-attached -property-causes-design-time-only-e/41617979 – 2017-01-13 09:56:52

1

試試這個:

<Setter TargetName="border" Property="BorderBrush" Value="{TemplateBinding Path=(local:ThemeProperties.ButtonBorderColour)}" /> 

的區別是酒店周圍的括號表明它是一個附加屬性。

+0

不幸的是,似乎沒有被認爲是有效的語法,它只是返回類型'(本地:ThemeProperties的「沒有找到的錯誤。 – thudbutt 2012-02-10 19:08:30

+2

對不起,你需要'路徑='在它的前面。在XAML解析器中出現了一個怪癖,我會更新我的答案 – 2012-02-10 19:40:10

+0

仍然沒有快樂,仍然被標記爲無效的語法,並且在'TemplateBindingExtension'類型中找不到'The property'Path'的錯誤。 – thudbutt 2012-02-10 21:07:03