【问题标题】:Unable to hook into PropertyChanged event using MVVM-Light无法使用 MVVM-Light 挂钩 PropertyChanged 事件
【发布时间】:2010-08-19 07:50:28
【问题描述】:

您好,创建了我的第一个基于 MVVM 的 WPF 应用程序,并试图弄清楚为什么我无法挂钩到依赖属性的 PropertyChanged 事件。

父视图模型中的代码:

void createClients()
{
    var clients = from client in Repository.GetClients()
                  select new ClientViewModel(Repository, client);
    foreach (var client in clients)
    {
        client.PropertyChanged += onClientPropertyChanged;
    }
    Clients = new ViewableCollection<ClientViewModel>(clients);
    Clients.CollectionChanged += onClientsCollectionChanged;
}

// Never gets called
void onClientPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if (e.PropertyName == "Name")
    {
         //...
    }
}

ViewableCollection 是 ObservableCollection 的简单扩展,用于封装 View。

ClientViewModel 中,setter 被调用,但 RaisePropertyChanged 没有像我预期的那样工作,因为onClientPropertyChanged 没有被调用。两个视图模型都继承自 ViewModelBase

public string Name
{
    get { return client.Name; }
    set
    {
        if (value == client.Name) return;
        client.Name = value;
        RaisePropertyChanged("Name");
    }
}

如果我将PropertyChanged 连接到ClientViewModel 内的一个方法,那么它就会被触发,所以我很难理解为什么这在父视图模型中不起作用。我哪里错了?

【问题讨论】:

  • 如何触发 Name 属性更改?如果是通过数据绑定,你使用的是双向模式吗?检查输出窗口是否有数据绑定错误。另外,您是否尝试过在 Name 属性设置器中设置断点,它是否被命中?
  • 嗨,马特,在这两个方面都是的,但我刚刚发现了另一个 SO 问题来解释这种行为。

标签: mvvm-light


【解决方案1】:

This SO question 解释问题; ObservableCollection 保护 PropertyChanged 事件。

一种解决方案是使用 MVVM-Light Messenger:

void createClients()
{
    var clients = from client in Repository.GetClients()
                  select new ClientViewModel(Repository, client);
    Clients = new ViewableCollection<ClientViewModel>(clients);
    Clients.CollectionChanged += onClientsCollectionChanged;
    Messenger.Default.Register<PropertyChangedMessage<string>>(this, (pcm) =>
    {
        var clientVM = pcm.Sender as ClientViewModel;
        if (clientVM != null && pcm.PropertyName == "Name")
        {
            // ...
        }
    });
}

createClients() 应该重构,但为了与问题代码保持一致,我将其保留在那里。然后对属性设置器稍作改动:

public string Name
{
    get { return client.Name; }
    set
    {
        if (value == client.Name) return;
        string oldValue = client.Name;
        client.Name = value;
        RaisePropertyChanged<string>("Name", oldValue, value, true);
    }
}

【讨论】:

  • -1 因为他没有处理 ObservableCollection 上的 PropertyChanged。他正在遍历集合并处理每个项目的 PropertyChanged。
  • 嗨,马特,我没关注你吗?没有迭代,只有一个注册来接收属性更改事件,以及一个消息广播以及属性设置器中的事件处理。如果 ObservableCollection 保护 PropertyChanged 事件,你如何处理它?
  • 好吧,我没有意识到你在回答你自己的问题。我一定完全误解了您遇到的问题,因为我不明白它与您的答案有何关系。所以不会让我取消投票,除非它被编辑(对不起)
  • 没问题,马特,我正在回答,因为如果你明白我的意思,在这个问题中回答会太混乱:)
猜你喜欢
  • 2016-02-27
  • 2017-12-18
  • 2015-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多