如何使用ICommand更改模型的属性?

时间:2017-09-11 14:11:22

标签: .net wpf mvvm observablecollection icommand

我正在制作一个Yahtzee游戏,试图学习WPF / MVVM。我已经取得了一些进展,但我正在努力研究如何使用ICommand给我的骰子一个随机的int值(“滚动”)。所以我有一个像这样的骰子类:

public class Die : INotifyPropertyChanged
    {
        int _id; 
        int _roll;
        bool _checked;
    }

这些属性都有这样的构造函数:

public bool Checked
    {
        get { return _checked; }
        set { _checked = value;
            OnPropertyChanged("Checked"); }
    }

“_ id”只是一种跟踪骰子的方法,甚至不确定是否需要。 “_roll”是一个随机值,这是手头的问题,“_ check”是玩家可以检查的复选框,如果他想为下一次投掷保留这个值。

我的ViewModel如下所示:

public class DiceViewModel : INotifyPropertyChanged
{
    Die _die;

    public DiceViewModel()
    {
        myDices = new ObservableCollection<Die>()
        {
            new Die { Id = 1, Roll = 0, Checked = false },
            new Die { Id = 2, Roll = 0, Checked = false },
            new Die { Id = 3, Roll = 0, Checked = false },
            new Die { Id = 4, Roll = 0, Checked = false },
            new Die { Id = 5, Roll = 0, Checked = false },
        };
    }
}

我创建命令的最佳尝试是这样的:

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

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

    public bool CanExecute (object parameter)
    {
        if ((bool)parameter == true)
        {
            return true;
        }
        else
            return false;
    }

    public void Execute(object parameter)
    {

    }
}

所以我无法理解如何创建的两件事是如何查看每个骰子的_checked属性是否为false,如果选中false,则给当前Die一个新数字。在点击我的“掷骰子”按钮后,我还需要遍历所有5个骰子。

  1. 我是否需要将RollDiceCommand放入其自己的文件中或将其与VM / M一起使用?
  2. 如何将_checked属性作为CanExecute参数
  3. 如何随机化一个骰子的_roll值,我猜问题2也解决了这个问题。

1 个答案:

答案 0 :(得分:0)

我会尽力帮助你如何做到这一点:

1)ObservableCollection是正确的选择,但是如果你需要来自该集合的信息,为什么不建立一个属性?然后你可以私下写/创建列表,到外面它只会是可读的

    public class DiceViewModel : INotifyPropertyChanged
    {
        Die _die;

        public DiceViewModel()
        {
            mMyDices= new ObservableCollection<Die>()
            {
                new Die { _id = 1, _roll = 0, _checked = false },
                new Die { _id = 2, _roll = 0, _checked = false },
                new Die { _id = 3, _roll = 0, _checked = false },
                new Die { _id = 4, _roll = 0, _checked = false },
                new Die { _id = 5, _roll = 0, _checked = false },
            };
        }
    private ObservableCollection<Die> mMyDices;
    public ObservableCollection<Die> MyDices 
    {
    public get {retrun mMyDices; }
    private set { SetProperty (mMyDices, value);     }
    //This is part from interface IProperty changed 
    }
}

2)如果你的命令是连接了GUI,那么是把它放在VM中 3)实现CanExecute方法的类,需要访问MyDices列表。要获得属性,您需要创建它们。

你的Dice类有3个私有变量。只有内部可见,就像1),使它们成为一个属性:

//to outside read-only, but only in Dice class is writable
public Checked {get; private set;} 

//to outside writable, readable
public Checked {get; set;} 

更新:

public abstract class BaseViewModel: INotifyPropertyChanged
    {
      /// <summary>
        ///     Multicast event for property change notifications.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        ///     Checks if a property already matches a desired value.  Sets the property and
        ///     notifies listeners only when necessary.
        /// </summary>
        /// <typeparam name="T">Type of the property.</typeparam>
        /// <param name="storage">Reference to a property with both getter and setter.</param>
        /// <param name="value">Desired value for the property.</param>
        /// <param name="propertyName">
        ///     Name of the property used to notify listeners.  This
        ///     value is optional and can be provided automatically when invoked from compilers that
        ///     support CallerMemberName.
        /// </param>
        /// <returns>
        ///     True if the value was changed, false if the existing value matched the
        ///     desired value.
        /// </returns>
        protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] String propertyName = null) {
            if (Equals(storage, value)) {
                return false;
            }

            storage = value;
            this.OnPropertyChanged(propertyName);
            return true;
        }

        /// <summary>
        ///     Notifies listeners that a property value has changed.
        /// </summary>
        /// <param name="propertyName">
        ///     Name of the property used to notify listeners.  This
        ///     value is optional and can be provided automatically when invoked from compilers
        ///     that support <see cref="CallerMemberNameAttribute" />.
        /// </param>
        protected void OnPropertyChanged([CallerMemberName] string propertyName = null) {
            PropertyChangedEventHandler eventHandler = this.PropertyChanged;
            if (eventHandler != null) {
                eventHandler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
}

我为VM创建了一个基类。