实现一个命令对象,用于更改viewmodel上的属性

时间:2016-07-20 19:34:40

标签: c# wpf xaml mvvm command

我正在尝试学习WPF / MVVM,出于教育原因,我创建了一个简单的应用程序。我在尝试实施Command Object时遇到了一些问题。

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

此外,我不想使用像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>

我的ModelView类

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"));
                }
            }
        }

(它也有一个数据绑定部分,但它与我的问题没有关系)

3 个答案:

答案 0 :(得分:2)

您希望视频模型中没有与颜色(画笔或画笔)等窗口相关的任何内容。请参阅下面的代码。

<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();
    }
}

答案 1 :(得分:0)

你不是很明确地陈述你的问题,但我赌博它是:如何为viewmodel的构造函数配置命令参数以使其更改backgroundcolour?

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

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

这很尴尬:命令是从viewmodel外部传递的,但它必须有一个引用来改变它的背景颜色。您可能想重新考虑您的设计。

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

public ICommand SubmitChangesCommand {get;set;}

答案 2 :(得分:0)

您需要为ICommand SubmitCommand创建公共属性,并且可以在其getter / setter中使用私有DelegateCommand。