简体   繁体   English

WPF MVVM动态更改静态资源样式

[英]WPF MVVM change static resource style dynamically

I am new to WPF and here is what I am trying to do. 我是WPF的新手,这是我想要做的。 I want to change a button's style, which is a static resource, based on whether a radio button is checked on not. 我想根据是否选中单选按钮来更改按钮的样式,这是一种静态资源。 Below is sample code: 下面是示例代码:

<RadioButton Name="rbInfoCorrect"
             GroupName="InfoQuestion"
             cal:Message.Attach="ShouldProceed">
      <RadioButton.Content>
        <TextBlock Text="Yes" Foreground="White"/>
      </RadioButton.Content>
</RadioButton>
<RadioButton Name="rbInfoNotCorrect"
             GroupName="InfoQuestion"
             cal:Message.Attach="ShouldStop">
      <RadioButton.Content>
        <TextBlock Text="No" Foreground="White"/>
      </RadioButton.Content>
</RadioButton>


<Button x:Name="btnProceed" cal:Message.Attach="Proceed">
  <Button.Style>
    <Style TargetType="Button" BasedOn="{StaticResource WhiteButton}"/>
  </Button.Style>
</Button>
<Button x:Name="btnStop" cal:Message.Attach="Stop">
  <Button.Style>
    <Style TargetType="Button" BasedOn="{StaticResource WhiteButton}"/>
  </Button.Style>
</Button>

So when 'Yes' is checked, I want to change the 'Proceed' button style to BlueButton (another static resource) and when 'No' is checked, I want to change the 'Stop' button style to BlueButton. 因此,当选中“是”时,我想将“继续”按钮样式更改为BlueButton(另一种静态资源),而当选中“否”时,我想将“停止”按钮样式更改为BlueButton。 Of course this is part of a bigger problem so I just trying to be specific with the sample example. 当然,这是一个更大的问题的一部分,因此,我仅尝试具体说明示例示例。

The part I am stuck at is how to update the StaticResource from WhiteButton to BlueButton based on the radio button checked status. 我停留的部分是如何根据单选按钮检查状态将StaticResource从WhiteButton更新为BlueButton。 Any direction would be greatly appreciated. 任何方向将不胜感激。

Thanks. 谢谢。

You don't need to change the whole Style to do that. 您无需更改整个Style即可。 You can just add a simple DataTrigger to react directly to the Checkbox.IsChecked property. 您只需添加一个简单的DataTrigger即可直接对Checkbox.IsChecked属性做出反应。 It's far simpler to declare the Style s like this instead: 像这样声明Style更加简单:

<Style x:Key="ProceedButtonStyle" TargetType="{x:Type Button}">
    <Setter Property="Background" Value="White" />
    <Style.Triggers>
        <DataTrigger Binding="{Binding IsChecked, ElementName=rbInfoCorrect}" 
            Value="True">
            <Setter Property="Background" Value="Blue" />
        </DataTrigger>
    </Style.Triggers>
</Style>

<Style x:Key="StopButtonStyle" TargetType="{x:Type Button}">
    <Setter Property="Background" Value="White" />
    <Style.Triggers>
        <DataTrigger Binding="{Binding IsChecked, ElementName=rbInfoNotCorrect}" 
            Value="True">
            <Setter Property="Background" Value="Blue" />
        </DataTrigger>
    </Style.Triggers>
</Style>

Even if you want more properties to change, you can just declare the default ones as plain Setter s and the ones triggered by the Checkbox.IsChecked property inside the DataTrigger . 即使您想更改更多属性,也可以将默认属性声明为Plain Setter ,并由DataTriggerCheckbox.IsChecked属性触发的属性。 If you have lots of common properties in the two Style s, then you can still declare them all in one and base the other one on that one and just add the different DataTrigger . 如果两个Style有很多公共属性,那么仍然可以将它们全部声明为一个,然后将另一个声明为基础,而只需添加不同的DataTrigger

We can replace the entire style using IMultiValue Converter. 我们可以使用IMultiValue Converter替换整个样式。

For your requirement I came up with this example 根据您的要求,我想到了这个例子

public class StyleConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType,
       object parameter, CultureInfo culture)
        {
            if (values.Length < 1)
                return Binding.DoNothing;
            bool isCorrect = (bool)values[0];
            bool isNotCorrect = (bool)values[1];
            Style firstStyle = (Style)values[2];
            Style secondStyle = (Style)values[3];
            if (isCorrect)
                return firstStyle;
            if (isNotCorrect)
                return secondStyle;
            return Binding.DoNothing;

        }

        public object[] ConvertBack(object value, Type[] targetTypes,
            object parameter, CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }

XAML XAML

<Window x:Class="StackWpf.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:StackWpf"
        Title="MainWindow" Name="window" Height="350" Width="525"  >
    <Window.Resources>

        <ResourceDictionary>
            <Style TargetType="Button" x:Key="WhiteStyle">
                <Setter Property="Background" Value="White"/>
            </Style>
            <Style TargetType="Button" x:Key="BlueStyle">
                <Setter Property="Background" Value="Blue"/>
            </Style>
            <local:StyleConverter x:Key="styleConverter"/>
        </ResourceDictionary>
    </Window.Resources>

    <Grid>
        <RadioButton Name="rbInfoCorrect" IsChecked="False"
             GroupName="InfoQuestion" Margin="80,19,382,257">
            <RadioButton.Content>
                <TextBlock Text="Yes" Foreground="Black"/>
            </RadioButton.Content>
        </RadioButton>
        <RadioButton Name="rbInfoNotCorrect" IsChecked="False"
             GroupName="InfoQuestion" Margin="80,38,391,257">
            <RadioButton.Content>
                <TextBlock Text="No" Foreground="Black"/>
            </RadioButton.Content>
        </RadioButton>
        <Button Content="Button" Margin="80,114,294,161">
            <Button.Style>


                        <MultiBinding Converter="{StaticResource styleConverter}">
                            <Binding ElementName="rbInfoCorrect"
                             Path="IsChecked" />
                            <Binding ElementName="rbInfoNotCorrect"
                             Path="IsChecked" />
                            <Binding Source="{StaticResource WhiteStyle}" />
                            <Binding Source="{StaticResource BlueStyle}" />
                        </MultiBinding>


            </Button.Style>
        </Button>

    </Grid>
</Window>

I have used this good article http://social.msdn.microsoft.com/Forums/vstudio/en-US/b25973bb-9e9c-4a99-8234-39a042e0a478/apply-styles-dynamically-to-buttons-in-xaml?forum=wpf earlier to tackle my issue. 我已经使用了这篇好文章http://social.msdn.microsoft.com/Forums/vstudio/en-US/b25973bb-9e9c-4a99-8234-39a042e0a478/apply-styles-dynamically-to-buttons-in-xaml吗? forum = wpf可以解决我的问题。

I'm not sure if you can replace the complete Style but you can user a DataTrigger to change some properties of the button: 我不确定是否可以替换完整的Style,但是可以使用DataTrigger更改按钮的某些属性:

    <Button.Style>
      <Style TargetType="Button" BasedOn="{StaticResource WhiteButton}">
        <Style.Triggers>
          <DataTrigger Binding="{Binding ElementName=rbInfoCorrect, Path=IsChecked}" Value="True">
            <Setter Property="Background" Value="White" />
          </DataTrigger>
          <DataTrigger Binding="{Binding ElementName=rbInfoCorrect, Path=IsChecked}" Value="False">
            <Setter Property="Background" Value="Blue" />
          </DataTrigger>
        </Style.Triggers>
      </Style>
    </Button.Style>

Check out http://Globalizer.codeplex.com . 查看http://Globalizer.codeplex.com

It switches out the entire style when it switches a language. 切换语言时,它将切换整个样式。

You basically look up the style in the resource dictionary, kill it and load a new one. 您基本上可以在资源字典中查找样式,将其杀死并加载一个新样式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM