无法使用 MVVM-Light 挂钩 PropertyChanged 事件

发布于 2024-09-14 20:35:16 字数 1331 浏览 3 评论 0原文

您好,创建我的第一个基于 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 的简单扩展来封装一个视图。

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 内的一个方法,那么它就会被触发,所以我很困惑为什么这在父视图模型中不起作用。我哪里出错了?

Greetings, creating my first MVVM based WPF app and trying to figure out why I'm unable to hook into the PropertyChanged event of a dependency property.

Code in the parent view model:

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 is a simple extension of ObservableCollection to encapsulate a View.

In the ClientViewModel the setters are being called but RaisePropertyChanged isn't working as I would expect, because onClientPropertyChanged isn't being invoked. Both view models inherit from ViewModelBase.

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

If I wire up PropertyChanged to a method inside the ClientViewModel then it is being fired, so I'm stumped as to why this isn't working in the parent view model. Where am I going wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

天冷不及心凉 2024-09-21 20:35:16

这个问题解释了问题; 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);
    }
}

This SO question explains the problem; ObservableCollection protects the PropertyChanged event.

One solution is to use 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() should be refactored, but for consistency with the question code I'll leave it in there. Then a slight change to the property setter:

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);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文