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