2012-02-10 15 views
20

Ho uno stile standard per i miei pulsanti ma desidero che determinate parti dello stile siano configurabili. per esempio. Appare un bordo quando MouseOver è attivato per il pulsante e voglio che il colore del bordo sia configurabile.Associazione modello con proprietà allegate

In seguito a questo articolo: http://www.thomaslevesque.com/2011/10/01/wpf-creating-parameterized-styles-with-attached-properties/ Ho pensato di poter utilizzare proprietà associate e TemplateBinding per ottenere ciò.

ho creato il seguente allegato:

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

ho impostato la proprietà in questo modo:

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

e il mio stile è simile al seguente:

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

dove la linea chiave è

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

Per quanto posso vedere questo dovrebbe funzionare ma ottengo il seguente errore durante l'esecuzione sulla riga sopra:

Non può convertire il valore di attributo 'valore' per oggetto di tipo ''. Errore nell'oggetto 'System.Windows.Setter' nel file markup

Ho fatto qualcosa di sbagliato qui? Sono nuovo di zecca per WPF e non riesco a capire cosa non va come il tipo di proprietà allegata è un pennello, che è quello che mi aspetterei che la proprietà BorderBrush di un bordo desideri.

risposta

39

Penso che TemplateBinding sia valutato in fase di compilazione, quindi non puoi impostare dinamicamente un TemplateBinding nel tuo Setter, prova invece ad usare Binding (vedi sotto).

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

Spero che questo aiuti.

+0

Hey ho modificato la mia risposta, dovrebbe funzionare ora. È stato un errore di sintassi, mi dispiace per quello. –

+0

Grazie a XiaoChuan, che ha funzionato perfettamente. Posso anche vedere la differenza tra il mio codice e l'esempio sulla pagina Web collegata, poiché l'esempio non utilizza TemplateBinding in un setter che non avevo apprezzato prima. Grazie ancora! – thudbutt

+0

Non capisco perché il mio caso identico non funzioni in fase di progettazione (ma lo fa in runtime) - http://stackoverflow.com/questions/41614676/binding-style-property-value-to-an-attached -property-causes-design-time-only-e/41617979 –

1

Prova questa:

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

La differenza è che le parentesi intorno alla proprietà indicano che si tratta di una proprietà associata.

+0

Sfortunatamente non sembra essere riconosciuto come sintassi valida e restituisce solo un errore di tipo '(locale: ThemeProperties' non trovato. – thudbutt

+2

Spiacente, hai bisogno di 'Path =' di fronte ad esso. una stranezza nel parser XAML Aggiornerò la mia risposta –

+0

Ancora nessuna gioia, ancora segnalata come sintassi non valida con l'errore "La proprietà 'Percorso' non è stata trovata nel tipo 'TemplateBindingExtension'". – thudbutt