我有一个名为EmployeeViewModel的viewmodel,它继承自ViewModelBase。这是ViewModelBase的实现。
public event PropertyChangedEventHandler PropertyChanged;
public void FirePropertyChanged(string propertyname)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyname));
}
public void FirePropertyChanged<TValue>(Expression<Func<TValue>> propertySelector)
{
if (PropertyChanged != null)
{
var memberExpression = propertySelector.Body as MemberExpression;
if (memberExpression != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(memberExpression.Member.Name));
}
}
}
我的EmployeeViewModel有一个属性名称GridResults,它绑定到View on Grid,这是属性定义。
public PagedCollectionView GridResults
{
get { return _gridResults; }
set
{
_gridResults = value;
FirePropertyChanged(()=>GridResults);
}
}
现在,当我在EmployeeViewModel的代码中的某处设置GridResults的值时,它会触发属性更改事件并进入
FirePropertyChanged(Expression&gt; propertySelector)
但在该方法中,其PropertyChangedEventHandler始终保持为null,并且它会阻止方法的完整执行。最终,我的网格视图仍未被注意到它的基础项源已被更改。
我错过了什么吗?
提前谢谢
-K9
答案 0 :(得分:1)
你的ViewModelBase真的实现了INotifyPropertyChanged吗?
如果是,请尝试使用字符串参数FirePropertyChanged。
public PagedCollectionView GridResults
{
get { return _gridResults; }
set
{
_gridResults = value;
FirePropertyChanged("GridResults");
}
}
这是我使用的INPCBase类:
/// <summary>
/// Basisklasse für INotifyPropertyChanged.
/// </summary>
public class INPCBase : INotifyPropertyChanged
{
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Notify mittels PropertyInfo. HINWEIS: diese Variante ist ungefähr 3x langsamer wie
/// <see cref="NotifyPropertyChanged(string)"/> bzw. <see cref="NotifyPropertyChanged(System.ComponentModel.PropertyChangedEventArgs)"/>.
/// </summary>
/// <example>
/// <code>
/// public string InfoMessage
/// {
/// get {return this.infomessage;}
/// set
/// {
/// this.infomessage = value;
/// this.NotifyPropertyChanged(()=> this.InfoMessage);
/// }
/// }
/// </code>
/// </example>
/// <typeparam name="T"></typeparam>
/// <param name="property"></param>
protected void NotifyPropertyChanged<T>(Expression<Func<T>> property)
{
var propertyInfo = ((MemberExpression)property.Body).Member as PropertyInfo;
if (propertyInfo == null)
{
throw new ArgumentException("The lambda expression 'property' should point to a valid Property");
}
this.VerifyPropertyName(propertyInfo.Name);
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyInfo.Name));
}
/// <summary>
/// Notify using pre-made PropertyChangedEventArgs
/// </summary>
/// <param name="args"></param>
protected void NotifyPropertyChanged(PropertyChangedEventArgs args)
{
this.VerifyPropertyName(args.PropertyName);
var handler = PropertyChanged;
if (handler != null)
{
handler(this, args);
}
}
/// <summary>
/// Notify using String property name
/// </summary>
protected void NotifyPropertyChanged(String propertyName)
{
this.VerifyPropertyName(propertyName);
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
#region Debugging Aides
/// <summary>
/// Warns the developer if this object does not have
/// a public property with the specified name. This
/// method does not exist in a Release build.
/// </summary>
[Conditional("DEBUG")]
[DebuggerStepThrough]
public void VerifyPropertyName(string propertyName)
{
// Verify that the property name matches a real,
// public, instance property on this object.
if (TypeDescriptor.GetProperties(this)[propertyName] != null)
return;
var msg = "Invalid property name: " + propertyName;
if (this.ThrowOnInvalidPropertyName)
throw new Exception(msg);
Debug.Fail(msg);
}
/// <summary>
/// Returns whether an exception is thrown, or if a Debug.Fail() is used
/// when an invalid property name is passed to the VerifyPropertyName method.
/// The default value is false, but subclasses used by unit tests might
/// override this property's getter to return true.
/// </summary>
protected virtual bool ThrowOnInvalidPropertyName { get; private set; }
#endregion // Debugging Aides
}