我正在制作一个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个骰子。
答案 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创建了一个基类。