0

我有一个名为 EmployeeViewModel 的视图模型,它继承自 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,它绑定到了Grid on View,这里是属性定义。

    public PagedCollectionView GridResults
    {
        get { return _gridResults; }
        set 
        { 
            _gridResults = value;
            FirePropertyChanged(()=>GridResults); 
        }
    }

现在,当我在 EmployeeViewModel 的代码中某处设置 GridResults 的值时,它会触发属性更改事件并进入

FirePropertyChanged(表达式> propertySelector)

但在该方法内部,它的 PropertyChangedEventHandler 始终保持为空,它会阻止方法的完全执行。最终,我的 Grid on View 仍然没有注意到它的底层 itemsource 已更改。

我错过了什么吗?

提前谢谢

-K9

4

1 回答 1

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
}
于 2010-09-16T14:16:50.223 回答