当静态属性的值改变时,视图没有得到通知
本文关键字:视图 通知 属性 静态 改变 | 更新日期: 2023-09-27 17:49:56
我有一个ViewModelBase类如下:
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public static event PropertyChangedEventHandler GlobalPropertyChanged = delegate { };
public static void OnGlobalPropertyChanged(string propertyName, Type className)
{
GlobalPropertyChanged(className,new PropertyChangedEventArgs(propertyName));
}
}
现在,我有另一个viewModel称为GroupViewModel继承ViewModelBase:
public class GroupViewModel : ViewModelBase
{
public GroupsViewModel()
{
CurrentGroup = new Group();
}
private static Group _currentGroup;
public static Group CurrentGroup
{
get
{
return _currentGroup;
}
set
{
_currentGroup = value;
OnGlobalPropertyChanged("CurrentGroup", typeof(Group));
}
}
}
现在在组中。xaml页面:
<Grid DataContext="{Binding CurrentGroup}">
.....
.....
<TextBlock Text="{Binding GroupName, TargetNullValue=''}" />
.....
.....
</Grid>
我有另一个ViewModel称为MainWindowViewModel,我尝试保存CurrentGroup到数据库像下面的代码,然后我设置CurrentGroup = new Group();
,但在组。xaml TextBox的文本未被清除:
Group group = GroupViewModel.CurrentGroup;
db.Groups.Add(group);
db.SaveChanges();
GroupViewModel.CurrentGroup = new Group();
更新:
如果我在GroupsViewModel中使用下面的代码,输出如预期的那样。我的意思是,当静态属性改变时,视图会更新。
public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged
= delegate { };
private static void NotifyStaticPropertyChanged(string propertyName)
{
StaticPropertyChanged(null, new PropertyChangedEventArgs(propertyName));
}
如果我在ViewModelBase中使用相同的代码(请注意GroupsViewModel继承了ViewModelBase),那么当静态属性的值发生变化时,视图不会更新。在这种情况下,我还将NotifyStaticPropertyChanged标记为公共,以避免编译时错误,如保护级别错误。
对于Static PropertyChanged
,您必须在类中创建像这样的通用静态事件:
public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged
= delegate { };
private static void NotifyStaticPropertyChanged(string propertyName)
{
StaticPropertyChanged(null, new PropertyChangedEventArgs(propertyName));
}
你必须调用就像你用来做实例属性一样:
NotifyStaticPropertyChanged("CurrentGroup");
但主要问题是在XAML中绑定-
您将在名称空间、类和属性周围使用括号因为WPF绑定引擎将路径解析为ClassName。PropertyName而不是PropertyName.PropertyName.
那么,它将是这样的:
<Grid DataContext="{Binding Path=(local:GroupViewModel.CurrentGroup)}">
.....
.....
<TextBlock Text="{Binding GroupName, TargetNullValue=''}" />
.....
.....
</Grid>
Source here INPC for static properties.
如果我在ViewModelBase中使用相同的代码(请注意GroupsViewModel继承ViewModelBase),则视图不更新时静态属性值改变
StaticPropertyChangedEvent
必须在属性所在的同一个类中。它不会像传统的INotifyPropertyChanged
那样工作,例如属性。
我没有任何MSDN文档来断言,但我通过调整事件代码来验证它,看看XAML是否从XAML连接到StaticPropertyChangedEvent
。
将事件代码替换为这个,您可以看到自己:
private static event EventHandler<PropertyChangedEventArgs> staticPC
= delegate { };
public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged
{
add { staticPC += value; }
remove { staticPC -= value; }
}
protected static void NotifyStaticPropertyChanged(string propertyName)
{
staticPC(null, new PropertyChangedEventArgs(propertyName));
}
添加一个断点,你会看到它会被击中,因为WPF绑定引擎内部挂钩到它来监听静态属性改变的事件。
但是一旦你移动到基类ViewModelBase,断点将不会被击中。因为WPF没有挂钩到它,所以任何属性的改变都不会明显地更新UI。
每当您想要更新特定数据类型的属性更改时,您需要在该数据类型中实现INotifyPropertyChanged
接口。这意味着如果您想要更新视图模型的属性更改,在您的示例中更改CurrentGroup
对象,则需要在视图模型中实现INotifyPropertyChanged
接口。
然而,看起来好像你实际上想要更新在 CurrentGroup
类内所做的属性更改(清除它们),所以在这种情况下,你需要在你的CurrentGroup
类中实现INotifyPropertyChanged
接口。我相信这就是@Silvermind所说的的意思。你需要触发与实例相关联的事件。