scott
scott

Reputation: 1277

PropertyGrid with possibly-null List

I'm using a PropertyGrid class to edit objects within my application. These are the relevant classes (or rather, simplifications thereof):

public class Inner
{
    public int A { get; set; }
    public string B { get; set; }
}

public class Outer
{
    public List<Inner> InnerData { get; set; }
    public int Id { get; set; }
}

I will set an object of type Outer as the SelectedObject field of my property grid. The problem comes when an Outer object has it's InnerData property set to null. Null is considered an acceptable value for this property as the InnerData property represents "optional" data, and not having it specified is not the same thing as specifying an empty list. Ideally I'd like a user to be able to replace a null InnerData property with a real value by specifying the components of the new list, modify an existing non-null InnerData value, and replace an existing InnerData value with null.

Anybody know how to make this happen?

Upvotes: 1

Views: 1157

Answers (2)

dmiranda84
dmiranda84

Reputation: 56

Have a look at creating a UITypeEditor, i think that if you use an editor you will have more control over the list and be able to tell if the current value is null and if so you can have the editor show a blank grid or something where list items can be added or removed, you could also add a checkbox to tell the editor to return null again and set null on the property, the editor is basically a WinForm so you can do almost anything in it.

internal class GenericTypeEditor : UITypeEditor
{
    public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
    {
        IWindowsFormsEditorService winFormEditorSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));

        using (MyForm editorForm = new MyForm())
        {
            if (winFormEditorSvc.ShowDialog(editorForm) == System.Windows.Forms.DialogResult.OK)
                value = editorForm.ReturnObject;
        }

        return value; //this can be null if you wish
    }

    public override UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
    {
        return UITypeEditorEditStyle.Modal;
    }
}

Then just set the attribute on your property

[EditorAttribute(typeof(GenericTypeEditor), typeof(System.Drawing.Design.UITypeEditor))]
public List<Inner> InnerData { get; set; }

This article helped me in the past, maybe it is of help to you: http://msdn.microsoft.com/en-us/library/ms171840(v=vs.100).aspx

Upvotes: 1

Wanabrutbeer
Wanabrutbeer

Reputation: 697

The property grid tries to add new Inner items to the InnerData object, but since you have not initialized it, the property grid has no where to save the added items. You need a constructor in Outter that will initialize InnerData just as a new List. You dont have to put any items into it, the user can do this at runtime, and can empty them back out as well, but the InnerData list Object needs to be initialized.

If you just want an Inner as a property, add System.ComponentModel to your usings and try this

[TypeConverter(typeof(ExpandableTypeConverter))]
public Inner DefaultInner { get; set; }

This will make your object expandable in the property grid so that you can set its nested properties

Try handling the PropertyGrid.SelectedGridItemChanged event:

private void propertyGrid1_SelectedGridItemChanged(object sender, SelectedGridItemChangedEventArgs e)
{
    if ((e.NewSelection.Label == "InnerData") && (_outter.InnerData == null)) _outter.InnerData = new List<Inner>();
}

Then whenever the InnerData item is selected, if the collection is null, its initialized to a new list.

Upvotes: 0

Related Questions