【问题标题】:How can I change my model's properties using ICommand?如何使用 ICommand 更改模型的属性?
【发布时间】:2017-09-11 14:11:22
【问题描述】:

我正在制作一个 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”是一个随机值,这是手头的问题,“_checked”是一个复选框,如果玩家想在下次投掷时保留这个值,可以勾选。

我的 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)
    {

    }
}

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

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

【问题讨论】:

  • 我不知道该告诉你什么,它在这里工作正常。或者至少它可以编译并运行而不会崩溃。编辑:我明白你的意思了,我要编辑它。
  • 我今天困了我不知道为什么我把"放在那里。

标签: .net wpf mvvm observablecollection icommand


【解决方案1】:

我会尽力帮助你的方式:

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 基类。

【讨论】:

  • 我似乎无法让“SetProperty”工作。我的错误消息显示“当前上下文中不存在名称‘SetProperty’。
  • 嗨,Tom,对不起,我忘了更新我的 Base 类的代码,这只会更新我的 VM 属性。
猜你喜欢
  • 2022-10-19
  • 2012-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-25
  • 1970-01-01
  • 2021-12-27
  • 2018-08-15
相关资源
最近更新 更多