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

时间:2014-03-12 08:48:15

标签: 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));
    }
}

现在,我有另一个名为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));
        }
    }
}

现在在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标记为公共,以避免编译时错误,例如有关保护级别的错误。

2 个答案:

答案 0 :(得分:10)

对于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>

来源INPC for static properties


<强>更新

  

如果我在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));
} 

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

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

答案 1 :(得分:1)

每当您想要更新特定数据类型的属性更改时,您需要在该数据类型中实现INotifyPropertyChanged接口。这意味着如果要更新视图模型的属性更改,在您的情况下更改CurrentGroup对象,则需要在视图模型中实现INotifyPropertyChanged接口

但是,似乎实际上想要更新 CurrentGroup类中的属性更改(以清除它们),所以在这种情况下,您还需要在INotifyPropertyChanged类中实现CurrentGroup接口。我相信这就是所指的@Silvermind你需要引发与实例相关联的事件。