C#的PropertyGrid控件支持给属性项自定义Converter和Editor,当指定从TypeConverter派生的Converter 时可以只能从下拉列表中选择,即属性值不可手工编辑,但不支持UserControl;而指定从UITypeEditor派生的Editor可以支持UserControl但又没办法限制用户直接编辑属性值。
    有时我们需要实现既能从UserControl中设定值又不想让用户直接编辑,就象一些Collection一样,只显示"(Collection)"串不可编辑又可以通过下拉或弹出窗体让用户选择。经过多次实现,发现属性项同时指定自定义Converter和Editor可以解决这个问题,后面附一些实现代码。
    定义属性项:
                private ItemContent _itemContent = new ItemContent();
                [EditorAttribute(typeof(ContentEditor), typeof(UITypeEditor)),
                TypeConverterAttribute(typeof(ConentConverter)),
                DescriptionAttribute("Select item content")]
                public ItemContent Content
                {
                        get { return _itemContent; }
                        set { _itemContent = value; }
                }
    定义属性内容类:
        public class ItemContent
        {
                private string _type = "Type";
                private string _c;

                public string Type
                {
                        get { return _type; }
                }

                public string Content
                {
                        get { return _content; }
                        set { _content = value; }
                }
        }
    定义Converter:
        public class ConentConverter : ExpandableObjectConverter
        {
                public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
                {
                        return true;
                }

                public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
                {
                        return true;
                }

                public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
                {
                        if (destinationType == typeof(ItemContent))
                        {
                                return true;
                        }

                        return base.CanConvertTo(context, destinationType);
                }

                public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
                {
                        if (destinationType == typeof(System.String) &&
                                value is ItemContent)
                        {
                                return "(Collection)";
                        }

                        return base.ConvertTo(context, culture, value, destinationType);
                }
        }
    定义Editor:
        public class ContentEditor : UITypeEditor
        {
                public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
                {
                        return UITypeEditorEditStyle.DropDown;
                }

                public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
                {
                        IWindowsFormsEditorService service = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
                        SelectControl ctrl = new SelectControl();

                        if (value is ItemContent)
                        {
                                ctrl.Selected = (value as ItemContent).Content;
                        }
                        service.DropDownControl(ctrl);

                        (value as ItemContent).Content = ctrl.Selected;

                        return value;
                }
        }
    实现SelectControl的UserControl,提供Selected属性,做一些操作。
    最后将包含有ItemContent属性的类对象赋给PropertyGrid的SelectedObject即可。

原文地址:http://blog.51haipai.com/article.asp?id=4