Mvvm FirePropertyChanged中的PropertyChangedEventHandler为空

Mvvm FirePropertyChanged中的PropertyChangedEventHandler为空,mvvm,viewmodel,inotifypropertychanged,event-handling,propertychanged,Mvvm,Viewmodel,Inotifypropertychanged,Event Handling,Propertychanged,我有一个名为EmployeeViewModel的viewmodel,它是从ViewModelBase继承的。下面是ViewModelBase的实现 public event PropertyChangedEventHandler PropertyChanged; public void FirePropertyChanged(string propertyname) { var handler = PropertyChanged; if (

我有一个名为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的值时,它触发属性更改事件并进入

FirePropertyChanged(表达式>属性选择器)

但在该方法中,其PropertyChangedEventHandler始终保持为null,并阻止方法的完全执行。最终,我的Grid on View没有注意到它的底层itemsource已经更改

我错过了什么吗

提前感谢


-K9

您的ViewModelBase真的实现了INotifyPropertyChanged吗

如果是,请尝试FirePropertyChanged with string参数

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
}
/// <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
}