【发布时间】:2018-03-29 21:05:05
【问题描述】:
背景
为了在 MVVM 应用程序中实现异步命令,我阅读了 Stephen Cleary 的以下教程。
- https://msdn.microsoft.com/magazine/dn605875 异步编程:异步 MVVM 应用程序的模式:数据绑定
- https://msdn.microsoft.com/en-us/magazine/dn630647.aspx 异步编程:异步 MVVM 应用程序的模式:命令
问题
在逐步重新实现他提出的建议时,我偶然发现了命令中的PropertyChanged 事件处理程序始终为null 的问题。运行 Steves 示例代码时,它不是 null。
为了更好地理解这一点,我从头开始实施人们能想到的最基本的命令:
public class SimpleCommand : ICommand, INotifyPropertyChanged
{
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
// having a break point on the following line
throw new NotImplementedException();
}
public event EventHandler CanExecuteChanged;
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
请注意,我在抛出NotImplementedException 的行上设置了一个断点,因为我只想看看PropertyChanged 是否为null。
视图模型基本上只是创建这个命令,视图通过一个按钮绑定到它。
public class MainViewModel : INotifyPropertyChanged
{
public ICommand SimpleAction { get; set; }
public MainViewModel()
{
SimpleAction = new SimpleCommand();
}
...
}
窗口只包含一个按钮来调用该命令
<Window ...>
<Window.DataContext>
<viewModels:MainViewModel></viewModels:MainViewModel>
</Window.DataContext>
<Grid>
<Button
Command="{Binding SimpleAction}"
Content="Click Me!"></Button>
</Grid>
</Window>
我的假设是,当命令实现 INotifyPropertyChanged 时,框架会监听 PropertyChanged 事件,这显然是错误的。
那么它在史蒂夫的例子中是如何工作的呢?在那里,他只是在NotifyTaskCompletion 或AsyncCommand 上实现INotifyPropertyChanged,而PropertyChanged 不是null。
查看其他 SO 帖子,通常的答案通常是 DataContext 未设置。我仍然看不到如何为命令设置它。
实际问题
如何在 MVVM (C#) 中的命令(基于ICommand)上正确实现INotifyPropertyChanged?
【问题讨论】:
-
您应该首先问的实际问题:WPF 应该听哪些属性更改?只要命令中的属性没有绑定到视图,就不需要监听器。
-
没错,你的命令没有提供任何属性给视图使用。您引用的示例是在 UI 中调用
Process complete,因此将附加一个侦听器。就像你的ViewModel有一个一样,如果你想使用它,你需要正确地复制这个例子。 -
在您的代码中我没有看到该教程中使用的
NotifyTaskCompletion... -
UI 只监听 ICommand 上的 CanExecuteChanged。我没有看到“史蒂夫的样本”,所以我不知道他在用它做什么。
-
@grek40 & XAMIMAX,你是对的。这正是问题所在。它仅在命令中至少有一个属性绑定到该属性时才有效。谢谢!
标签: c# wpf mvvm async-await