无法使用MVVM-Light挂接到PropertyChanged事件

时间:2010-08-19 07:50:28

标签: mvvm-light

问候,创建我的第一个基于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内的方法,那么它就会被触发,所以我很难过为什么这在父视图模型中不起作用。我哪里错了?

1 个答案:

答案 0 :(得分: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);
    }
}