我有一个 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));
}
}
现在,我有另一个名为 GroupViewModel 的 View 模型,它继承了 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));
}
}
}
现在在 Groups.xaml 页面中:
<Grid DataContext="{Binding CurrentGroup}">
.....
.....
<TextBlock Text="{Binding GroupName, TargetNullValue=''}" />
.....
.....
</Grid>
我有另一个名为 MainWindowViewModel 的 ViewModel,我尝试像下面的代码一样将 CurrentGroup 保存到数据库,然后设置
CurrentGroup = new Group();
但在 Group.xaml 中,TextBox 的文本未清除:Group group = GroupViewModel.CurrentGroup;
db.Groups.Add(group);
db.SaveChanges();
GroupViewModel.CurrentGroup = new Group();
更新:
如果我在 GroupsViewModel 中使用以下代码,则输出符合预期。我的意思是当静态属性更改时更新 View 。
public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged
= delegate { };
private static void NotifyStaticPropertyChanged(string propertyName)
{
StaticPropertyChanged(null, new PropertyChangedEventArgs(propertyName));
}
如果我在 ViewModelBase 中使用相同的代码(请注意 GroupsViewModel 继承了 ViewModelBase),那么当静态属性的值更改时,View 不会更新。此外,在这种情况下,我已将 NotifyStaticPropertyChanged 标记为 public 以避免编译时错误,例如有关保护级别的错误。
最佳答案
对于 Static PropertyChanged
,您必须在类中创建这样的通用静态事件:
public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged
= delegate { };
private static void NotifyStaticPropertyChanged(string propertyName)
{
StaticPropertyChanged(null, new PropertyChangedEventArgs(propertyName));
}
并且您必须像使用实例属性一样调用:
NotifyStaticPropertyChanged("CurrentGroup");
但主要的问题是在 XAML 中,您正在绑定(bind) -
所以,它会是这样的:
<Grid DataContext="{Binding Path=(local:GroupViewModel.CurrentGroup)}">
.....
.....
<TextBlock Text="{Binding GroupName, TargetNullValue=''}" />
.....
.....
</Grid>
来源 INPC for static properties 。
更新
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));
}
在 add 上放置一个断点,您将看到它会被命中,因为 WPF 绑定(bind)引擎在内部 Hook 到它以监听静态属性更改事件。
但是一旦您将其移动到基类 ViewModelBase,就不会命中断点。因为,WPF 还没有钩住它,所以属性的任何更改都不会明显更新 UI。
关于c# - 当静态属性的值发生变化时, View 不会收到通知,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22346212/