tags:

views:

320

answers:

2

I have an element and multiple styles, how do I switch between the styles at runtime either programatically or through XAML binding.

<Rectangle x:Name="fixtureControl" Style="{DynamicResource FixtureStyle_Fast}">

<!-- In the style resources. -->
<Style x:Key="FixtureStyle_Fast" TargetType="{x:Type Shape}">
    <Setter Property="Stroke" Value="Black"/>
    <Setter Property="StrokeThickness" Value="20"/>
</Style>

<Style x:Key="FixtureStyle_Good" TargetType="{x:Type Shape}">
    <Setter Property="Effect">
        <Setter.Value>
            <DropShadowEffect Opacity=".9"
                              Direction="-90"
                              RenderingBias="Performance"
                              BlurRadius="50"
                              ShadowDepth="10" />
        </Setter.Value>
    </Setter>
</Style>

<Style x:Key="FixtureStyle_Best" TargetType="{x:Type Shape}">
    <Setter Property="Effect">
        <Setter.Value>
            <DropShadowEffect Opacity=".9"
                              Direction="-90"
                              RenderingBias="Quality"
                              BlurRadius="50"
                              ShadowDepth="10" />
        </Setter.Value>
    </Setter>
</Style>

Then I have some radio buttons that handle changing the style

private void RadioButton_Click(object sender, RoutedEventArgs e) {
    if (e.Source == rdoQualityBest) {
        fixtureControl.Style = FindResource("FixtureStyle_Best") as Style;
    } else if (e.Source == rdoQualityGood) {
        fixtureControl.Style = FindResource("FixtureStyle_Good") as Style;
    } else {
        fixtureControl.Style = FindResource("FixtureStyle_Fast") as Style;
    }
}

However this applies the style to the element, not replacing it, so if I apply Fast then Quality, I get both the border and the drop-shadow.

A: 

It is working fine for me

here is my code:

in .xaml

    <Window.Resources>
    <Style x:Key="FixtureStyle_Fast" TargetType="{x:Type Shape}">
        <Setter Property="Stroke" Value="Black"/>
        <Setter Property="StrokeThickness" Value="20"/>
    </Style>

    <Style x:Key="FixtureStyle_Good" TargetType="{x:Type Shape}">
        <Setter Property="Stroke" Value="Red"/>
        <Setter Property="StrokeThickness" Value="20"/>
    </Style>

    <Style x:Key="FixtureStyle_Best" TargetType="{x:Type Shape}">
        <Setter Property="Stroke" Value="Blue"/>
        <Setter Property="StrokeThickness" Value="20"/>
    </Style>
</Window.Resources>
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>
     <Rectangle x:Name="fixtureControl" Style="{DynamicResource FixtureStyle_Fast}"/>
    <StackPanel Grid.Column="1">
    <RadioButton Name="rdoQualityBest" Content="Best" Click="RadioButton_Click" />
    <RadioButton Name="rdoQualityGood" Content="Good" Click="RadioButton_Click" />
    <RadioButton Name="rdoQualityFast" Content="Fast" Click="RadioButton_Click" />
    </StackPanel>
</Grid>

in .xaml.cs

private void RadioButton_Click(object sender, RoutedEventArgs e)
{
    if (e.Source == rdoQualityBest)
    {
        fixtureControl.Style = FindResource("FixtureStyle_Best") as Style;
    }
    else if (e.Source == rdoQualityGood)
    {
        fixtureControl.Style = FindResource("FixtureStyle_Good") as Style;
    }
    else
    {
        fixtureControl.Style = FindResource("FixtureStyle_Fast") as Style;
    }
}
viky
In all of the styles in your example you are setting the same properties, so it's being overridden when the new style is applied. What appeared to be happening for me was that if I had one style that only set the "Stroke" property, and another that only filled the "StrokeThickness" then only that property would be applied, it wouldn't reset the other propertie(s).
Brett Ryan
+1  A: 

Something like this has worked for me in the past (a pure XAML solution):

<!-- Styles 1-4 defined somewhere else on your page -->
<ComboBox Name="AvailableStyles">
    <ComboBoxItem Tag="{x:Null}" IsSelected="True">None</ComboBoxItem>
    <ComboBoxItem Tag="{StaticResource Style1}">1</ComboBoxItem>
    <ComboBoxItem Tag="{StaticResource Style2}">2</ComboBoxItem>
    <ComboBoxItem Tag="{StaticResource Style3}">3</ComboBoxItem>
    <ComboBoxItem Tag="{StaticResource Style4}">4</ComboBoxItem>
</ComboBox>

<Button Content="Button" Style="{Binding ElementName=AvailableStyles, Path=SelectedItem.Tag}"/>
<CheckBox Content="Check Box" Style="{Binding ElementName=AvailableStyles, Path=SelectedItem.Tag}"/>
<RadioButton Content="Radio Button"Style="{Binding ElementName=AvailableStyles, Path=SelectedItem.Tag}"/>

Hope this helps!

Pwninstein
You know I almost did this but assumed it would behave the same as how I was changing through code. I'm surprised that this actually works and am interested to know why it doesn't work through code by simply applying the style. Fantastic Pwninstein, this works great :)
Brett Ryan
I'm not 100% sure why the code approach works differently, but I think it's because when you set the Style via Binding, it knows how to "undo" everything when switching between styles. Just a guess. Either way, glad that helped!
Pwninstein