2012-02-10 11 views
20

Mam standardowy styl dla moich przycisków, ale chcę, aby pewne części stylu były konfigurowalne. na przykład Pojawia się ramka, gdy dla przycisku uruchamiany jest MouseOver i chcę, aby kolor ramki był konfigurowalny.Oprawa szablonów z załączonymi właściwościami

Po tym artykule: http://www.thomaslevesque.com/2011/10/01/wpf-creating-parameterized-styles-with-attached-properties/ Pomyślałem, że mogę użyć dołączonych właściwości i TemplateBinding, aby to osiągnąć.

stworzyłem następujące załączony właściwość:

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)); 
} 

ustawić właściwość tak:

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

A mój styl wygląda następująco:

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

gdzie klucz linia to

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

O ile widzę, to powinno działać, ale pojawia się następujący komunikat o błędzie podczas wykonywania na powyższej linii:

Nie można przekonwertować wartości w atrybucie „wartość” do obiektu typu „”. Błąd w obiekcie "System.Windows.Setter" w pliku znaczników

Czy zrobiłem tutaj coś niepoprawnego? Jestem całkowicie nowy w WPF i nie mogę określić, co się dzieje, ponieważ Typ załączonej nieruchomości to Pędzel, którego oczekuję od właściwości BorderBrush.

Odpowiedz

39

Myślę, że TemplateBinding jest oceniany w czasie kompilacji, więc nie można dynamicznie ustawić TemplateBinding w seter, spróbuj użyć Binding zamiast (patrz poniżej).

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

Mam nadzieję, że to pomoże.

+0

Hej, zredagowałem moją odpowiedź, teraz powinno działać. To był błąd w składni, przykro mi z tego powodu. –

+0

Dzięki XiaoChuan, który działa doskonale. Widzę również różnicę między moim kodem a przykładem na połączonej stronie internetowej, ponieważ przykład nie korzysta z TemplateBinding w setera, którego wcześniej nie doceniałem. Dzięki jeszcze raz! – thudbutt

+0

Nie rozumiem, dlaczego mój identyczny przypadek nie działa w czasie projektowania (ale ma to miejsce w czasie wykonywania) - http://stackoverflow.com/questions/41614676/binding-style-property-value-to-an-attached -property-powoduje-projekt-czas-tylko-e/41617979 –

1

Spróbuj tego:

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

tą różnicą, że nawiasy wokół nieruchomości wskazują, że jest on przymocowany nieruchomość.

+0

Niestety, nie wydaje się, że jest rozpoznana jako poprawna składnia i po prostu zwraca błąd typu "(nie znaleziono elementu local: ThemeProperties.) – thudbutt

+2

Niestety, potrzebujesz' Path = 'przed nim. dziwactwo w parserze XAML Zaktualizuję moją odpowiedź –

+0

Nadal nie ma radości, nadal oznaczona jako nieprawidłowa składnia z błędem "Ścieżka właściwości" nie została znaleziona w typie "TemplateBindingExtension" ". – thudbutt