【问题标题】:Implement INotifyPropertyChanged on ICommand在 ICommand 上实现 INotifyPropertyChanged
【发布时间】:2018-03-29 21:05:05
【问题描述】:

背景

为了在 MVVM 应用程序中实现异步命令,我阅读了 Stephen Cleary 的以下教程。

问题

在逐步重新实现他提出的建议时,我偶然发现了命令中的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


【解决方案1】:

除非您绑定到命令本身的属性,否则命令本身没有订阅者。

这就是@Stephen Cleary 在他的文章中所做的。他绑定到AsyncCommand&lt;TResult&gt; 类的Execution 属性。您绑定到MainViewModel 类的SimpleAction 属性。

所以在您的示例代码中,SimpleCommand 对象没有订阅者,这就是事件处理程序返回 null 引用的原因。

【讨论】:

  • 不,我知道了。而已。所以仅仅有一个实现INotifyPropertyChanged 的类是不够的。需要至少有一个绑定到该类,以便框架侦听PropertyChanged。谢谢。
猜你喜欢
  • 2010-11-30
  • 1970-01-01
  • 2017-07-31
  • 2011-01-09
  • 2010-10-04
  • 2021-06-29
  • 2012-12-17
  • 1970-01-01
  • 2014-06-02
相关资源
最近更新 更多