我正在学习wpf,代表,事件以及我对什么做了一些线索,但在实施ICommand
时我有点迷失
我有一个类实现了ICommand
接口,就像这样
class RelayCommand : ICommand
{
private Action<object> _execute;
private Func<object, bool> _canExecute;
public RelayCommand(Action<object> execute) : this (execute, null)
{
}
public RelayCommand(Action<object> execute, Func<object,bool> canExecute)
{
this._execute = execute;
this._canExecute = canExecute;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
//throw new NotImplementedException();
return true;
}
public void Execute(object parameter)
{
//throw new NotImplementedException();
this._execute(parameter);
}
public void OnCanExecute()
{
if (CanExecuteChanged != null)
{
CanExecuteChanged(this, EventArgs.Empty);
}
}
然后我的ViewModel使用i。
class PersonViewModel
{
public ICommand ICommandPresenter { get; set; }
public PersonModel PM;
private string _btnString = "";
#region Propertys
public string ButtonString
{
get {return _btnString; }
set
{
if (_btnString.Equals(value))
{
return;
}
_btnString = value;
}
}
public string Name { get { return PM.Name; } set
{
PM.Name = value;
}
}
#endregion Propertys
public PersonViewModel()
{
PM = new PersonModel();
ICommandPresenter = new RelayCommand(ChangeName);
}
public void ChangeName(object a)
{
string s = a as string;
MessageBox.Show("Hello from PersonViewModel Commander: " + s);
}
}
这让我感到困惑。在RelayCommand
类中,我有一个事件CanExecuteChanged
,但该事件从未执行/触发。从我对事件的阅读中所理解的是,你并不“需要”拥有一个事件的订阅者,但是如果你想要一个事件,你至少应该在执行它的代码中的某个地方。但我在我的代码中没有这个,但由于某种原因,我的按钮仍然按照我的命令执行。我仍然明白我点击了按钮,但我的代码中没有订阅该按钮的任何内容。
CanExecuteChanged
事件相关联的订阅者,它会变得无用吗? 答案 0 :(得分:0)
CanExecuteChanged是ICommand类的成员,并且简化了一些事情,wpf框架使用它来启用/禁用您的按钮,具体取决于CanExecute()方法的结果。单击按钮时,CanExecute对于您要执行的代码并不紧密,但对于完成合法的条件,CanExecute是不紧的。
Command执行你的代码,因为你在这里发送指向你的方法的指针(ChangeName方法):
ICommandPresenter = new RelayCommand(ChangeName);
所以你根本没有使用CanExecuteChange
,因为你正在调用这个构造函数:
public RelayCommand(Action<object> execute)
。
要使用CanExecute,您必须调用接受CanExecute谓词的重载构造函数:
public RelayCommand(Action<object> execute, Func<object,bool> canExecute)
要调用它,只需传递一个返回bool作为第二个参数的函数:
ICommandPresenter = new RelayCommand(ChangeName, ()=>MyCustomLogicWhenButtonIsActive());
答案 1 :(得分:0)
根据我在.Net的源代码中看到的内容,分配给按钮的Command
属性的命令以下列方式执行:
OnClick()
方法(位于按钮的ButtonBase
基类中)。OnClick()
方法(see source here)调用Commands.CommandHelpers.ExecuteCommandSource()
方法,将this
作为命令源参数传递。ExecuteCommandSource()
(see source here)进一步调用CriticalExecuteCommandSource()
方法,将相同的命令源作为参数传递。CriticalExecuteCommandSource()
方法(see source here)访问命令源的Command
成员,并且:
CanExecute()
方法是否返回true
,true
,则会调用命令的Execute()
方法。RelayCommand
实现,那么显然,RelayCommand
类会在您实例化时将调用传递给您传递给其构造函数的特定方法。) 所以,回答你的问题是否通过事件触发命令:
源指示OnClick()
方法直接执行命令,而不是通过事件处理。正如您在源代码中看到的,此方法 引发Click
事件,但它与命令执行分开。
尽管如此,框架首先如何调用OnClick()
方法仍然没有答案;我根本不知道。