PropertyValueChanged event not firing for Custom Collections

G

Guest

I've been using a PropertyGrid to display an object containing a property
that is a Custom Collection. I created a UITypeEditor for this Custom
Collection and associated it with the property via the EditorAttribute:

<code>
public class ObjectContainingCustomCollectionAsProperty
{
private CustomCollection m_CustomCollection;

[Editor(typeof(CustomCollectionEditor),typeof
(System.Drawing.Design.UITypeEditor))]
DescriptionAttribute("Custom Collection"),
TypeConverter(typeof(CustomCollectionConverter))]
public CustomCollection CustomColl
{
get
{
return m_CustomCollection;
}
set
{
m_CustomCollection = value;
}
}
}

internal class CustomCollectionConverter : TypeConverter {

public override object ConvertTo(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture, object value, Type destType)
{
if (destType == typeof(string) && value is CustomCollection)
{
return "Custom Collection";
}
return base.ConvertTo(context, culture, value, destType);
}
}

public class CustomCollectionEditor : UITypeEditor
{


public override UITypeEditorEditStyle GetEditStyle(
ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.DropDown;
}

public override object
EditValue(System.ComponentModel.ITypeDescriptorContext context,
IServiceProvider provider, object value)
{
IWindowsFormsEditorService wfes = provider.GetService(
typeof(IWindowsFormsEditorService)) as
IWindowsFormsEditorService;

if (wfes != null)
{
ObjectContainingCustomCollectionAsProperty obj =
(ObjectContainingCustomCollectionAsProperty)context.Instance;

CustomCollection c = obj.CustomColl;
CheckedListBox lb = new CheckedListBox();
for(int i=0;i<CustomCollection.Count();i++)
{

lb.Items.Add(c.GetName(i));
if (c)
{
lb.SetItemChecked(i, true);
}
}

wfes.DropDownControl(lb);



for(int i=0;i<lb.Items.Count;i++)
{

if (lb.GetItemCheckState(i) == CheckState.Checked)
{
c = true;
}
else
{
c = false;
}
}

//Note: you must clone the collection
//or PropertyGrid's GridItem doesn't
//commit the change -- (since it
//and doesn't commit a change
//if new value == old value
//which it will if the value is
//reference type)
value = c.Clone();

}
return value;
}
}
</code>

I had problems with the above code UNTIL I used Lutz Roeder's awesome tool
--.NET Reflector tool -- free off the internet at
http://www.aisto.com/roeder/dotnet/
and looked at the PropertyGrid source code -- there's a method in class
GridEntry
used by the PropertyGridView inside of PropertyGrid called
EditPropertyValue. This method does the following check:

<code>
internal virtual void EditPropertyValue(PropertyGridView iva)
{
....
object obj1 = this.PropertyValue;
object obj2 = this.UITypeEditor.EditValue(this,this,obj1);
if(this.Disposed)
{
return;
}

if((obj1 != obj1) && this.IsValueEditable)
{
iva.CommitValue(this,obj2);
}
....}//end of method EditPropertyValue(PropertyGridView iva)
</code>

So the punchline to this whole story is IF YOU'RE USING A PROPERTY IN THE
PROPERTY GRID THAT IS A REFERENCE TYPE THEN BE SURE TO RETURN A CLONE OF THAT
REFERENCE TYPE FROM YOUR UITYPEEDITOR CLASS'S EDITVALUE METHOD!!!!!

Thanks for letting me share this -- I was very happy to finally discover this.
Now if only Microsoft allowed you to debug into their framework such
problems would be even easier to resolve! ; )
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top