PropertyGrid with possible-null List

时间:2012-10-23 23:04:28

标签: c# .net propertygrid

我正在使用PropertyGrid类来编辑应用程序中的对象。这些是相关的类(或更确切地说,简化):

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; }
}

我将Outer类型的对象设置为属性网格的SelectedObject字段。当一个外部对象将其InnerData属性设置为null时,就会出现问题。 Null被认为是此属性的可接受值,因为InnerData属性表示“可选”数据,并且未指定它与指定空列表不同。理想情况下,我希望用户能够通过指定新列表的组件,修改现有的非null InnerData值,并将现有的InnerData值替换为null来将null InnerData属性替换为实际值。

有人知道如何实现这一目标吗?

2 个答案:

答案 0 :(得分:1)

看看创建UITypeEditor,我认为如果你使用编辑器,你将有更多的控制列表,并能够判断当前值是否为null,如果是这样,你可以让编辑器显示一个空格或者可以添加或删除列表项的东西,你也可以添加一个复选框来告诉编辑器再次返回null并在属性上设置null,编辑器基本上是一个WinForm,所以你几乎可以做任何事情。

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;
    }
}

然后只需在您的属性上设置属性

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

这篇文章过去帮助了我,也许对你有所帮助: http://msdn.microsoft.com/en-us/library/ms171840(v=vs.100).aspx

答案 1 :(得分:0)

属性网格尝试将新的内部项添加到InnerData对象,但由于您尚未初始化它,因此属性网格无法保存添加的项。在Outter中需要一个构造函数,它将初始化InnerData,就像一个新的List一样。您不必将任何项目放入其中,用户可以在运行时执行此操作,也可以将其清空,但需要初始化InnerData列表对象。

如果您只想将Inner作为属性,请将System.ComponentModel添加到您的使用中并尝试此操作

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

这将使您的对象在属性网格中可扩展,以便您可以设置其嵌套属性

尝试处理PropertyGrid.SelectedGridItemChanged事件:

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

然后,只要选择了InnerData项,如果集合为null,则将其初始化为新列表。