将命令抽象到视图模型中是XAML / MVVM项目的一项有价值的实践。我明白了。而且,我在WinRT中看到了ICommand;但是,我们如何实现它?我还没有找到实际可行的样本。有人知道吗?
答案 0 :(得分:20)
我最喜欢的是Microsoft模式和实践团队提供的DelegateCommand。它允许您创建一个类型化的命令:
MyCommand = new DelegateCommand<MyEntity>(OnExecute);
...
private void OnExecute(MyEntity entity)
{...}
它还提供了一种引发CanExecuteChanged事件的方法(禁用/启用命令)
MyCommand.RaiseCanExecuteChanged();
以下是代码:
public class DelegateCommand<T> : ICommand
{
private readonly Func<T, bool> _canExecuteMethod;
private readonly Action<T> _executeMethod;
#region Constructors
public DelegateCommand(Action<T> executeMethod)
: this(executeMethod, null)
{
}
public DelegateCommand(Action<T> executeMethod, Func<T, bool> canExecuteMethod)
{
_executeMethod = executeMethod;
_canExecuteMethod = canExecuteMethod;
}
#endregion Constructors
#region ICommand Members
public event EventHandler CanExecuteChanged;
bool ICommand.CanExecute(object parameter)
{
try
{
return CanExecute((T)parameter);
}
catch { return false; }
}
void ICommand.Execute(object parameter)
{
Execute((T)parameter);
}
#endregion ICommand Members
#region Public Methods
public bool CanExecute(T parameter)
{
return ((_canExecuteMethod == null) || _canExecuteMethod(parameter));
}
public void Execute(T parameter)
{
if (_executeMethod != null)
{
_executeMethod(parameter);
}
}
public void RaiseCanExecuteChanged()
{
OnCanExecuteChanged(EventArgs.Empty);
}
#endregion Public Methods
#region Protected Methods
protected virtual void OnCanExecuteChanged(EventArgs e)
{
var handler = CanExecuteChanged;
if (handler != null)
{
handler(this, e);
}
}
#endregion Protected Methods
}
答案 1 :(得分:3)
查看RelayCommand课程(仅限METRO代码)。可以找到NotifyPropertyChanged
课程here。 NotifyPropertyChanged
类仅用于允许CanExecute
上的绑定,并使用RaiseCanExecuteChanged
进行更新。
可以找到原始中继命令类here
答案 2 :(得分:2)
不幸的是,似乎没有为您实现它的本机类。如果你想自己实现它,界面不是太复杂,流行的 MVVM Lite 工具包包含自己的 RelayCommand 版本。您可以通过右键单击References并选择“Manage NuGet Packages”将MVVM Lite添加到您的项目中。如果您没有此选项,请在工具 - &gt;下启用Nuget。扩展程序和更新。
答案 3 :(得分:0)
我一直在寻找XAML-MVVM命令的最小端到端实现,但还没有找到它。
所以,按照#Rico的回答,我最终将以下内容作为最小的RelayCommand工作。我在一个大项目中使用了类似的最小版本。
public class RelayCommand : System.Windows.Input.ICommand {
readonly Action<object> execute;
public RelayCommand(Action<object> execute) {
this.execute = execute;
}
public bool CanExecute(object parameter) {
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter) {
this.execute(parameter);
}
}
较大的RelayCommand类似乎可以提供对CanExecute
和CanExecuteChanged
的更多控制权,但您并不需要这样做才能开始使用 - 您可能根本不需要它。
要在视图模型中使用它:
class ViewModel : INotifyPropertyChanged {
<< ... snip VM properties and notifications ...>>
public RelayCommand DoSomethingCommand {
get {
return new RelayCommand(param => {
this.DoSomething(param as AType);
Debug.WriteLine("Command Executed");
});
}
}
}
(我们不需要命令的INotifyPropertyChanged,但任何视图模型通常都会实现它。)
最后,XAML ......
<Grid>
<!-- Set the data context here, for illustration. -->
<Grid.DataContext>
<local:ViewModel/>
</Grid.DataContext>
<!-- A sample control bind to a property -->
<TextBlock
Text="{Binding AProp}"/>
<!-- Bind a command -->
<Button Command="{Binding DoSomethingCommand}" CommandParameter="foo">Change!</Button>
</Grid>
答案 4 :(得分:0)
我发现这是一个非常好的例子 https://code.msdn.microsoft.com/windowsapps/Working-with-ICommand-690ba1d4
<Page.Resources>
<local:MyCommandsCollection x:Key="MyCommands" />
</Page.Resources>
<Button Width="280"
Height="59"
Margin="513,280,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Command="{Binding MyFirstCommand}"
CommandParameter="{Binding Text,
ElementName=myTextBox}"
Content="Execute Command" />
public class MyCommandsCollection
{
public MyCommand MyFirstCommand
{
get { return new MyCommand(); }
}
}
public class MyCommand : ICommand
{
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public async void Execute(object parameter)
{
MessageDialog message = new MessageDialog(
"The command is executing, the value of the TextBox is " + parameter as String);
await message.ShowAsync();
}
}
我用x:Bind尝试了这个,它很好用。我需要的是在我的ViewModel中公开一个属性,该属性返回一个新的“MyCommand”类实例,这一切都很好。
由于我在我的XAML中设置了DataContext,所以我不需要搞乱任何“MyCommandCollection”的东西。 Yay编译绑定。