当静态属性更改的值时,不会收到视图通知

Vis*_*hal 4 c# wpf xaml

我有一个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));
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,我有另一个名为GroupViewModel的viewModel,它继承了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));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在在Groups.xaml页面:

<Grid DataContext="{Binding CurrentGroup}">
    .....
    .....
    <TextBlock Text="{Binding GroupName, TargetNullValue=''}" />
    .....
    .....
</Grid>
Run Code Online (Sandbox Code Playgroud)

我有另一个名为MainWindowViewModel的ViewModel,我尝试将CurrentGroup保存到数据库,如下面的代码然后我设置CurrentGroup = new Group();但在Group.xaml中TextBox的文本没有被清除:

Group group = GroupViewModel.CurrentGroup;
db.Groups.Add(group);
db.SaveChanges();
GroupViewModel.CurrentGroup = new Group();
Run Code Online (Sandbox Code Playgroud)

更新:

如果我在GroupsViewModel中使用以下代码,则输出符合预期.我的意思是静态属性更改时更新View.

public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged
         = delegate { };
private static void NotifyStaticPropertyChanged(string propertyName)
{
   StaticPropertyChanged(null, new PropertyChangedEventArgs(propertyName));
}
Run Code Online (Sandbox Code Playgroud)

如果我在ViewModelBase中使用相同的代码(请注意,GroupsViewModel继承ViewModelBase),则静态属性的值更改时不会更新View.此外,我在这种情况下将NotifyStaticPropertyChanged标记为公共,以避免编译时错误,如有关保护级别的错误.

Roh*_*ats 11

因为Static PropertyChanged你必须在你的类中创建这样的通用静态事件:

public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged
         = delegate { };
private static void NotifyStaticPropertyChanged(string propertyName)
{
   StaticPropertyChanged(null, new PropertyChangedEventArgs(propertyName));
}
Run Code Online (Sandbox Code Playgroud)

你必须像你用来做实例属性一样调用:

NotifyStaticPropertyChanged("CurrentGroup");
Run Code Online (Sandbox Code Playgroud)

但主要的问题是在XAML中你有约束力 -

您将在命名空间,类和属性周围使用括号,因为WPF绑定引擎将路径解析为ClassName.PropertyName而不是PropertyName.PropertyName.

所以,它会是这样的:

<Grid DataContext="{Binding Path=(local:GroupViewModel.CurrentGroup)}">
  .....
  .....
  <TextBlock Text="{Binding GroupName, TargetNullValue=''}" />
  .....
  .....
</Grid>
Run Code Online (Sandbox Code Playgroud)

来源INPC为静态属性.


UPDATE

如果我在ViewModelBase中使用相同的代码(请注意,GroupsViewModel继承ViewModelBase),则静态属性的值更改时不会更新View.

StaticPropertyChangedEvent必须在属性所在的同一个班级.它不会像传统INotifyPropertyChanged的属性那样工作.

我没有任何MSDN文档来断言,但我通过调整事件代码来验证它是否与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));
} 
Run Code Online (Sandbox Code Playgroud)

在add上添加一个断点,你会发现它会被点击,因为WPF绑定引擎在内部挂钩它以监听静态属性更改事件.

但是只要将其移动到基类ViewModelBase,断点就不会被击中.因为,WPF没有挂钩,所以任何属性的更改都不会明显更新UI.