NotifyPropertyChanged Stack overflow

Jan 16, 2012 at 9:16 PM
Edited Jan 16, 2012 at 9:22 PM

In response to a INPC, the new value is set using Value which, which will set the value on the BusinessObject, which may trigger a new NotifyPropertyChanged. This is no problem if the BusinessObject only sends INPC when the property differs, but one Itested with always send it.

Here is the fix:

Index: Apps/CMAXRemote/SL4PropertyGrid/PropertyItem.cs
===================================================================
--- Apps/CMAXRemote/SL4PropertyGrid/PropertyItem.cs	(revision 71881)
+++ Apps/CMAXRemote/SL4PropertyGrid/PropertyItem.cs	(working copy)
@@ -57,7 +57,7 @@
 		void PropertyItem_PropertyChanged(object sender, PropertyChangedEventArgs e)
 		{
 			if (e.PropertyName == this.Name)
-				Value = _propertyInfo.GetValue(_instance, null);
+                SetValueOnly(_propertyInfo.GetValue(_instance, null));
 		}
 		#endregion
 
@@ -98,6 +98,14 @@
 			}
 		} private string _category;
 
+        internal void SetValueOnly(object value)
+        {
+            if (_value == value) 
+                return;
+            _value = value;
+            OnPropertyChanged("Value");
+        }
+
 		public object Value
 		{
 			get { return _value; }

Coordinator
Jan 16, 2012 at 9:29 PM

Not sure I see the difference? The Value property setter checks to see if the new value is different then the current one already.

Jan 16, 2012 at 9:33 PM

If you look at the Value property set handler, you can see that the  _propertyInfo.SetValue is called which can trigger a new NotifyPropertyChange.

public object Value
{
	get { return _value; }
	set
	{
		if (_value == value) return;
		object originalValue = _value;
		_value = value;
		try
		{
			Type propertyType = this._propertyInfo.PropertyType;
			if (((propertyType == typeof(object)) || ((value == null) && propertyType.IsClass)) || ((value != null) && propertyType.IsAssignableFrom(value.GetType())))
			{
				_propertyInfo.SetValue(_instance, value, (BindingFlags.NonPublic | BindingFlags.Public), null, null, null);
				OnPropertyChanged("Value");
			}
			else
			{
....

Coordinator
Jan 16, 2012 at 9:56 PM

But only if it's a different value, and if it is, then it should. Correct?

The first line checks - if (_value == value) return;

Jan 16, 2012 at 11:02 PM
Edited Jan 17, 2012 at 5:38 AM

Ahh now i see the real problem.

if (_value == value)  just checks if its the same object instance.
Replacing it with the code below fixes it.

if
 (_value.Equals(value))
    return;

or maby

if (_value!=null && _value.Equals(value))
    return;

Coordinator
Jan 17, 2012 at 2:39 PM

Good catch!

Below is the new check logic. I've added a special check for strings.

if (_value != null)
{
	if ((value != null && (value is string || _value is string)) && _value.ToString() == value.ToString())
		return;
	else if (_value.Equals(value))
		return;
	_value = value;
}
else
{
	if (null == value)
		return;
	_value = value;
}