在 ViewModel 中存储信息或使用 IValueConverter

Storing information in ViewModel or using IValueConverter

如果我想将 wpf 中的 ButtonBackground 颜色更改为红色,如果我的视图模型中的 属性 Amount0 如果它大于 0 则变为绿​​色,为此使用值转换器更好,还是我应该简单地在我的视图模型中实现自定义 Background-属性? Background-属性 会将 Amount 值包装到 SolidColorBrush,它将绑定到 ButtonBackground

哪种方式更直接?

谢谢!

我会用 Trigger 做,但 Converter 也可以。但是我肯定不会在ViewModel中做属性 Background,因为Background是关于设计的,是关于view的,所以最好在View

中定义

我会使用 DataTrigger.

将以下样式应用到您的按钮。

它绑定到视图模型中的 Amount 属性。 它将默认背景色设置为 'green',如果 Amount 的值为 0,则更改为 'red'。

<Button.Style>
    <Style TargetType="Button">
        <Setter Property="Background" Value="Green" />
        <Style.Triggers>
            <DataTrigger Binding="{Binding Amount}" Value="0">
                <Setter Property="Background" Value="Red" />
            </DataTrigger>
        </Style.Triggers>
    </Style>
</Button.Style>


附加信息

您还可以使用 MultiDataTrigger.

检查多个条件

看起来像这样:

<MultiDataTrigger>
    <MultiDataTrigger.Conditions>
        <Condition Binding="{...}, Value="..."/>
        <Condition Binding="{...}, Value="..."/>
    </MultiDataTrigger.Conditions>
    <MultiDataTrigger.Setters>
        <Setter Property="A" Value="..."/>
        <Setter Property="B" Value="..."/>
    </MultiDataTrigger.Setters>
</MultiDataTrigger>

查看 this article 如何使用它。

似乎要进行范围检查,您需要实施 IValueConverter,就像其他回复或 this answer 中提到的那样。

设置 Buttonbackground 与视图相关 我不认为从 ViewModel 设置它是个好主意,我认为如果您定义Amount 属性 在 ViewModel 中,定义一个 DataTrigger 来检查 amount 值 对照 0 使用 转换器

<Window.Resources>
    <YurNs:GreaterThanValConverter x:Key="GreaterThanValConverter"/>
</Window.Resources>
<StackPanel>
    <TextBox Text="{Binding Amount,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
    <Button Content="Button">
        <Button.Style>
            <Style TargetType="Button">
                <Setter Property="Background" Value="Green"/>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Amount,Converter={StaticResource GreaterThanValConverter}}" Value="false">
                        <Setter Property="Background" Value="Red"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Button.Style>
    </Button>      
</StackPanel>

和转换器

 public  class GreaterThanValConverter:IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (int) value > 0;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

您还可以考虑将参数传递给转换器进行比较,以便您的解决方案尽可能可定制。

我会在 viewmodel 中制作 bool 属性,这是在 Amount 更改时计算的:

public bool IsAmountZero
{
    get { return Amount == 0; }
}

private int _amount;
public int Amount
{
    get { return _amount; }
    set
    {
        _amount = value;
        OnPropertyChanged();
        OnPropertyChanged(nameof(IsAmountZero));
    }
}

然后编写转换器BoolToColorConverter(颜色可以通过ConverterParameter以某种方式)。

// in current form it's actually BoolToColorRedGreenConverter
public class BoolToColorConverter : MarkupExtension, IValueConverter
{
    public BoolToColorConverter() { }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is bool)
        {
            var colorFalse = Colors.Green;
            var colorTrue = Colors.Red;
            if (parameter != null)
            {
                //...
            }
            return (bool)value ? colorTrue : colorFalse;
        }
        throw new InvalidCastException();
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

这样使用

    <Button.Background>
        <SolidColorBrush Color="{Binding IsAmountZero, Converter={local:BoolToColorConverter}}" />
    </Button.Background>

这将是一个可重用的解决方案。

否则只需制作转换器 IntZeroCheckToColorGreenRedConverter,但与具有 bool 属性.

的转换器相比,它的可重用性不会很高

在视图模型中使用 Brush 属性 的想法很糟糕,因为视图模型并不真正关心颜色。 Viewmodel 应该只包含与模型相关的逻辑,然后由视图使用。如果你想简单地改变颜色(例如使用 Blue 而不是 Green)——这个改变必须在视图中完成。因此 bool 属性 和 BoolToColorConverter(或 BoolToSolidBrushConverter 直接与 xaml 中的 Background 属性一起使用)转换器。