问题描述
如何从viewmodel修改Style属性?我在Caliburn Micro上使用WPF和MVVM。我的按钮有两种样式,当用户单击按钮时,我想从viewmodel中更改它。
我正在xaml中使用它:
<Button
Style="{Binding Path=StyleButton,Mode=OneWay}"
Grid.Row="0"
Grid.Column="1"
Content="News"
x:Name="LoadFirstPage" />
请客气,我是wpf世界中的新手:)
解决方法
在视图模型中放置诸如Style
之类的与视图相关的类型违反了MVVM原则。而是公开一个属性,该属性表示按钮的状态,该按钮确定应显示一种样式还是另一种样式。
public class MyViewModel : INotifyPropertyChanged
{
private bool _isPageLoaded;
public bool IsPageLoaded
{
get => _isPageLoaded;
set
{
if (_isPageLoaded == value)
return;
_isPageLoaded = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this,new PropertyChangedEventArgs(propertyName));
}
// ...other properties and methods.
}
确保给它起一个有意义的名字。它不必为bool
类型,但是适合这里。另外,请确保实施INotifyPropertyChanged
以反映对用户界面中属性的更改。
在单击按钮时调用的命令或方法中,将此属性设置为正确的值。从这里开始,您可以选择多种方案。
样式触发解决方案
代替完全交换样式,您可以使用触发器根据存储在属性中的状态对属性进行不同设置的两种状态创建通用样式。
<Style x:Key="MyButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
<!-- Properties set for IsPageLoaded=False -->
<Setter Property="Foreground" Value="Red"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsPageLoaded}" Value="True">
<!-- Properties set for IsPageLoaded=True -->
<Setter Property="Foreground" Value="Blue"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Button Style="{StaticResource MyButtonStyle}"
Grid.Row="0"
Grid.Column="1"
Content="News"
x:Name="LoadFirstPage"/>
价值转换器解决方案
您可以创建一个值转换器,该值转换器返回与属性状态相对应的样式。
public class ConditionToStyleConverter : IValueConverter
{
public Style SuccessStyle { get; set; }
public Style FailureStyle { get; set; }
public object Convert(object value,Type targetType,object parameter,CultureInfo culture)
{
return (bool)value ? SuccessStyle : FailureStyle;
}
public object ConvertBack(object value,CultureInfo culture)
{
return new InvalidOperationException();
}
}
这是您在范围中的资源字典中放置的两种样式和一个转换器的示例。
<Style x:Key="MyFirstButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Foreground" Value="Red"/>
</Style>
<Style x:Key="MySecondButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Foreground" Value="Blue"/>
</Style>
<local:ConditionToStyleConverter x:Key="ConditionToStyleConverter"
SuccessStyle="{StaticResource MyFirstButtonStyle}"
FailureStyle="{StaticResource MySecondButtonStyle}"/>
您可以像这样在按钮上使用转换器。
<Button Style="{Binding IsPageLoaded,Converter={StaticResource ConditionToStyleConverter}}"
Grid.Row="0"
Grid.Column="1"
Content="News"
x:Name="LoadFirstPage"/>
在此示例中,转换器是一个简单的IValueConverter
,它公开了样式的属性,因此对于不同的样式,您将不得不创建其他实例。也可以创建一个可以直接绑定样式的多值转换器,但是对于初学者来说,此解决方案就足够了。