如果您愿意,可以很简单地避免将您的 ViewModel 耦合到 ICommand。可能不是一个坏主意,WPF 可能有一天会走上 MFC 的道路。矫枉过正?也许,但这是一个方法:
在您看来:
<StackPanel>
<Button Command="{Binding Path=MyCommand}"> Do it! Kill me Now!</Button>
<TextBlock Text="{Binding Path=Message}"></TextBlock>
</StackPanel>
将您的 ViewModel 注入您的 DataContext,从您的视图模型中承担本机命令的责任:
public class ViewModel : INotifyPropertyChanged
{
public string Message { get; set; }
public object MyCommand { get; set; }
public void OnMyCommand(object parameter)
{
Message += "I Ran something" + Environment.NewLine;
}
public bool CanMyCommand(object parameter)
{
return true;
}
// Injected Native Command handler
public ViewModel(ICommandFactory factory)
{
MyCommand = factory.CreateInstance(OnMyCommand, CanMyCommand);
}
public event PropertyChangedEventHandler PropertyChanged;
}
注意我使用FODY来编织属性更改处理程序。INotifyPropertyChanged 是 System.dll 顺便说一句。
现在,绑定这个合约:
public interface ICommandFactory
{
object CreateInstance(Action<object> action, Func<object, bool> predicate);
}
... 给你一个原生的 Command 对象的东西;
public class NativeCommand : ICommand
{
private readonly Action<object> _action;
private readonly Func<object, bool> _predicate;
public NativeCommand(Action<object> action, Func<object, bool> predicate)
{
_action = action;
_predicate = predicate;
}
public bool CanExecute(object parameter)
{
return _predicate(parameter);
}
public void Execute(object parameter)
{
_action(parameter);
}
public event EventHandler CanExecuteChanged;
}
public class NativeCommandFactory : ICommandFactory
{
public object CreateInstance(Action<object> action, Func<object, bool> predicate)
{
return new NativeCommand(action, predicate);
}
}
Bind<ICommandFactory>().To<NativeCommandFactory>();
瞧,解耦的命令。
另请注意,您的注入是在初始应用程序启动时完成的。您的 ViewModel 与您选择的任何 IoC 容器分离。