【问题标题】:PropertyChangedEventHandler is null in FirePropertyChangedFirePropertyChanged 中的 PropertyChangedEventHandler 为空
【发布时间】:2011-04-13 04:49:35
【问题描述】:

我有一个名为 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(Expression> propertySelector)

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

我错过了什么吗?

提前致谢

-K9

【问题讨论】:

    标签: mvvm viewmodel inotifypropertychanged event-handling propertychanged


    【解决方案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
    }
    

    【讨论】:

      猜你喜欢
      • 2012-12-25
      • 2011-04-05
      • 2012-02-15
      • 1970-01-01
      • 1970-01-01
      • 2011-06-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多