在我的视图模型上实现一个更改 属性 的命令对象

Implement a Command Object that changes a property on my viewmodel

我正在努力学习 WPF/MVVM,出于教育原因,我创建了一个简单的应用程序。我在尝试实施 Command Object.

时遇到了一些问题

单击按钮控件时,我希望使用 Command Object 将网格的背景色更改为黄色。有很多关于如何做到这一点的东西,但我想用干净的方式来做。通常我想在 ViewViewModelCommand Object 之间实现松耦合,以便测试那些 classes.

我也不想使用像Prism这样的库,因为我需要先完全理解 MVVM。

我有一个代码示例,但它当然没有功能。只是为了方便起见。

我的观点XAML

<Window x:Class="Calendar.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:Calendar"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="480">

<Grid Background="{Binding BackgroundColour}" Margin="0,0,2,0">
    <Button Margin="197,247,200,-239" Grid.Row="3" Grid.ColumnSpan="2" Command="{Binding SubmitCommand}">Color</Button>
</Grid>

我的模型视图class

public class MainWindowViewModel : INotifyPropertyChanged {

    //Command part
    ICommand SubmitCommand;
    public MainWindowViewModel(ICommand command) {
        SubmitCommand = command;
    }

    //Data Binding part
    public event PropertyChangedEventHandler PropertyChanged;
    private Brush backgroundColour = (Brush)new BrushConverter().ConvertFromString("Red");
    public Brush BackgroundColour {
        get { return this.backgroundColour; }
        set {
            if (value != this.backgroundColour) {
                this.backgroundColour = value;
                var handler = this.PropertyChanged;
                if (handler != null) {
                    handler(this, new PropertyChangedEventArgs("BackgroundColour"));
                }
            }
        }

(它也有数据绑定部分,但它与我的问题无关)

你没有很清楚地说明你的问题,但我赌它是:如何为视图模型的构造函数配置命令参数以使其更改背景颜色?

命令通过让它们实现来完成它们的工作 ICommand.Execute(Object) 所以基本上你想让你传递给构造函数的命令对象有一个像这样的方法:

void Execute(object parameter)
    {
        viewModel.BackGroundColor=Brushes.Yellow;
    }

这很尴尬:命令是从视图模型外部传递的,但它必须引用它才能更改其背景颜色。您可能需要重新考虑您的设计。

此外:要让数据绑定引擎看到 SubmitChangedCommand,它必须是 属性:

public ICommand SubmitChangesCommand {get;set;}

您需要为 ICommand SubmitCommand 创建一个 public 属性 并且您可以在其 getter/setter.

您不希望视图模型中有任何与 windows 相关的颜色(画笔或画笔)。参考我下面的代码。

<Window x:Class="MVVMNav_Learning.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:MVVMNav_Learning"
    mc:Ignorable="d"
    Title="Window1" Height="300" Width="300">
<Window.Resources>
    <local:ColorConverterConverter x:Key="ColorConverterConverter"></local:ColorConverterConverter>
</Window.Resources>
<Grid>
    <Grid Background="{Binding BackgroundColour,Converter={StaticResource ColorConverterConverter}}" Margin="0,0,2,0">
        <Button Margin="50"  Command="{Binding SubmitCommand}">Color</Button>
    </Grid>
</Grid>

 public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();
        this.DataContext = new ViewModel();
    }
}

public class ViewModel:INotifyPropertyChanged
{
    private MyColor backColor;

    public MyColor BackgroundColour
    {
        get { return backColor; }
        set { backColor = value; OnPropertyChanged("BackgroundColour"); }
    }

    public ICommand SubmitCommand { get; set; }

    public ViewModel()
    {
        BackgroundColour = MyColor.Red;
        SubmitCommand = new BaseCommand(Execute);
    }

    public void Execute(object parameter)
    {
        BackgroundColour = MyColor.Yellow;
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }
    }
}

public enum MyColor
{
    Red,
    Green,
    Yellow
}

public class BaseCommand : ICommand
{
    private Action<object> _method;
    public event EventHandler CanExecuteChanged;

    public BaseCommand(Action<object> method)
    {
        _method = method;
    }

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public void Execute(object parameter)
    {
        _method.Invoke(parameter);
    }
}

public class ColorConverterConverter : IValueConverter
{
    public object Convert(object value, Type targetType,
        object parameter, CultureInfo culture)
    {
        MyColor color = (MyColor)value;
        switch (color)
        {
            case MyColor.Red:
                return Brushes.Red;
            case MyColor.Green:
                return Brushes.Green;
            case MyColor.Yellow:
                return Brushes.Yellow;
            default:
            {
                return Brushes.Red;
            }
        }
    }

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