我有一个 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/

10-12 07:40
查看更多