我有一个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标记为公共,以避免编译时错误,例如有关保护级别的错误。
答案 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>
<强>更新强>
如果我在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你需要引发与实例相关联的事件。