1
Vote

ObservableObject.VerifyPropertyName excludes static or protected properties

description

The VerifyPropertyName debugging code fails if used on a static or protected properties.
This changes the test to work for the more general case. (It allows private properties but there isn't an easy way to exclude them.)
 
Matt Heffron
 
public void VerifyPropertyName(string propertyName)
{
  // If you raise PropertyChanged and do not specify a property name,
  // all properties on the object are considered to be changed by the binding system.
  if (String.IsNullOrEmpty(propertyName))
    return;
 
  // Verify that the property name matches a real property on this object.
  try
  {
    PropertyInfo propertyInfo = this.GetType().GetProperty(propertyName,
                                                         BindingFlags.Public | BindingFlags.NonPublic |
                                                         BindingFlags.Static | BindingFlags.Instance |
                                                         BindingFlags.FlattenHierarchy);
    if (propertyInfo == null)
    {
      string msg = "Invalid property name: " + propertyName;
 
      if (this.ThrowOnInvalidPropertyName)
        throw new ArgumentException(msg);
      else
        Debug.Fail(msg);
    }
  }
  catch (AmbiguousMatchException)
  {
    return;   // Well...the name *IS* there...
  }
}

comments

JoshSmithOnWpf wrote Nov 4, 2009 at 5:08 AM

Matt,

Thanks for your feedback.

I had considered adding support for non-public properties, but it presented oddities so I didn't do it. I built ObservableObject to make it easy to notify the WPF binding system of property changes. A Binding can only bind to public properties on an object, so it seemed like a bug to consider a protected/internal/private property as "valid" when raising PropertyChanged. Suppose I have an object with two properties: PublicProp and ProtectedProp (whose access modifiers are implied by the property names). If I accidentally pass "ProtectedProp" to RaisePropertyChanged() from the PublicProp setter, it would be considered valid. That might seem like a bug. Perhaps you can convince me otherwise...

Please explain the static property scenario. What use case do you have in mind?

Thanks,
Josh

MattHeffron wrote Nov 4, 2009 at 7:49 PM

I have several ViewModel classes that have static properties exposing "almost constant" collections that I bind to. (The collection values are constant, but need to be sorted based on the CurrentCulture which can be changed on-the-fly.) I need to be able to RaisePropertyChanged() on those properties when the CurrentCulture changes so WPF gets the reordered collection.

I'm willing to concede non-public properties as a potential bug. I don't need them. (I sort-of went overboard with the GetProperty flags.)

JoshSmithOnWpf wrote Nov 6, 2009 at 3:19 PM

I see what you mean, Matt. I am thinking of maybe adding a static version of RaisePropertyChanged. Alternatively, could you have those static collections be ObservableCollections (or ReadOnlyObservableCollections) to get the change notifications you need? Thanks!

Josh

JoshSmithOnWpf wrote Nov 6, 2009 at 3:21 PM

On second thought, how would the binding system know which class the property belongs to? If you were to raise PropertyChanged where e.PropertyName="FooProperty" and sender=null, how would a binding know which class FooProperty is on? I've never tried this, and am not sure if it would even work.

Josh

MattHeffron wrote Nov 6, 2009 at 5:31 PM

But the RaisePropertyChanged, at least in my case, does pass an instance of the class as the sender. (The class is not static, but the property is.)

wrote Feb 21, 2013 at 11:05 PM