当静态属性的值改变时,视图没有得到通知

本文关键字:视图 通知 属性 静态 改变 | 更新日期: 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所说的的意思。你需要触发与实例相关联的事件。