Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binding for WPF Styles

I'm trying to create a custom control - a button - which will have multiple styles applied to it depending on the value of a property within the data context.

What I was thinking is using something similar to:

<Button Style="{Binding Path=ButtonStyleProperty, Converter={StaticResource styleConverter}}" Text="{Binding Path=TextProp}" /> 

And in code... Implement an IValueConverter which does something similar to the code below in the ConvertTo method:

switch(value as ValueEnums) {     case ValueEnums.Enum1:         FindResource("Enum1ButtonStyle") as Style;     break;      ... and so on. }  

However I'm not entirely sure about how to pull out the style object and even if this is possible at all...

What I am doing in the mean time is handling the DataContextChanged event, then attaching a handler to the PropertyChanged event of the object being bound to the button - then running the switch statement in there.

Its not quite perfect but until I can find a better solution it seems like that is what I'll have to use.

like image 790
Matthew Savage Avatar asked Jan 04 '09 06:01

Matthew Savage


People also ask

How do I apply a style in WPF?

To apply the style, set the Style property on the element to the x:Key value, using a StaticResource markup extension, as shown here. Notice that the first TextBlock element has the style applied to it while the second TextBlock element remains unchanged.

How do I apply multiple styles in WPF?

To apply the multiple styles as you phrase it above, the best bet is to use triggers. In future version of WPF, the VisualStateManager will be introduced which supports the visual state transition between different set of setters, triggers, and animations which could enable a broader styling scenarios.


2 Answers

If you want to replace the whole style (rather than just elements of it) then you'll probably be storing those styles in resources. You should be able to do something along the lines of:

<Button>     <Button.Style>         <MultiBinding Converter="{StaticResource StyleConverter}">             <MultiBinding.Bindings>                 <Binding RelativeSource="{RelativeSource Self}"/>                 <Binding Path="MyStyleString"/>             </MultiBinding.Bindings>         </MultiBinding>     </Button.Style> </Button> 

By using a MultiBinding and using Self as the first binding we can then lookup resources in our converter. The converter needs to implement IMultiValueConverter (rather than IValueConverter) and can look something like this:

class StyleConverter : IMultiValueConverter  {     public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)     {         FrameworkElement targetElement = values[0] as FrameworkElement;          string styleName = values[1] as string;          if (styleName == null)             return null;          Style newStyle = (Style)targetElement.TryFindResource(styleName);          if (newStyle == null)             newStyle = (Style)targetElement.TryFindResource("MyDefaultStyleName");          return newStyle;     }      public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)     {         throw new NotImplementedException();     } } 

It's not something I do very often, but that should work from memory :)

like image 120
Steven Robbins Avatar answered Sep 24 '22 21:09

Steven Robbins


It seems that you need to use DataTrigger class. It allows you to apply different styles to your button based on it's content.

For example following style will change button's background property to red based on value of data context object's property

<Style x:Key="ButtonStyle" TargetType="{x:Type Button}">     <Style.Triggers>         <DataTrigger Binding="{Binding Path="Some property"}"                       Value="some property value">             <Setter Property="Background" Value="Red"/>         </DataTrigger>     </Style.Triggers> </Style> 
like image 38
aku Avatar answered Sep 25 '22 21:09

aku