【问题标题】:Using the .NET collection editor without using a property grid control使用 .NET 集合编辑器而不使用属性网格控件
【发布时间】:2009-01-23 16:17:41
【问题描述】:

我的表单上有一个 PropertyGrid。我的老板认为这很丑陋。粗野。朴实无华。

他想要一个漂亮、整洁、干净的表格。这里有一个问题:其中一个属性是我们自产的对象的集合。他喜欢这个集合的集合编辑器。

我知道我可以构建自己的收藏编辑器。但是有没有一个干净、简单的解决方案可以节省我几个小时的编码时间,这样我就可以直接创建和使用集合编辑器而不使用属性网格?

【问题讨论】:

    标签: c# .net collections propertygrid


    【解决方案1】:

    您可以从UITypeEditor(通过TypeDescriptor)获得此功能,但这并不简单——您需要设置IServiceProvider、IWindowsFormsEditorService,最好是ITypeDescriptorContext——相当有点花哨。如果您不熟悉这些工具,手动操作可能会更简单。

    或者 - 看看SmartPropertyGrid.NET,PropertyGrid 的替代品。


    更新:这是一个工作示例...绝对不平凡,但请随意窃取代码。它仅适用于模态编辑器,不适用于下拉菜单。它也不是“关注点分离”的一个很好的例子。 MyHelper 类很有趣。

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Drawing.Design;
    using System.Windows.Forms;
    using System.Windows.Forms.Design;
    class Foo
    {
        public Foo() { Bars = new List<Bar>(); }
        public List<Bar> Bars { get; private set; }
    }
    class Bar
    {
        public string Name { get; set; }
        public DateTime DateOfBirth { get; set; }
    }
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Foo foo = new Foo();
            Bar bar = new Bar();
            bar.Name = "Fred";
            bar.DateOfBirth = DateTime.Today;
            foo.Bars.Add(bar);
            Application.EnableVisualStyles();
            using(Form form = new Form())
            using (Button btn = new Button())
            {
                form.Controls.Add(btn);
                btn.Text = "Edit";
                btn.Click += delegate
                {
                    MyHelper.EditValue(form, foo, "Bars");
                };
                Application.Run(form);
            }
        }
    }
    
    class MyHelper : IWindowsFormsEditorService, IServiceProvider, ITypeDescriptorContext
    {
        public static void EditValue(IWin32Window owner, object component, string propertyName) {
            PropertyDescriptor prop = TypeDescriptor.GetProperties(component)[propertyName];
            if(prop == null) throw new ArgumentException("propertyName");
            UITypeEditor editor = (UITypeEditor) prop.GetEditor(typeof(UITypeEditor));
            MyHelper ctx = new MyHelper(owner, component, prop);
            if(editor != null && editor.GetEditStyle(ctx) == UITypeEditorEditStyle.Modal)
            {
                object value = prop.GetValue(component);
                value = editor.EditValue(ctx, ctx, value);
                if (!prop.IsReadOnly)
                {
                    prop.SetValue(component, value);
                }
            }
        }
        private readonly IWin32Window owner;
        private readonly object component;
        private readonly PropertyDescriptor property;
        private MyHelper(IWin32Window owner, object component, PropertyDescriptor property)
        {
            this.owner = owner;
            this.component = component;
            this.property = property;
        }
        #region IWindowsFormsEditorService Members
    
        public void CloseDropDown()
        {
            throw new NotImplementedException();
        }
    
        public void DropDownControl(System.Windows.Forms.Control control)
        {
            throw new NotImplementedException();
        }
    
        public System.Windows.Forms.DialogResult ShowDialog(System.Windows.Forms.Form dialog)
        {
            return dialog.ShowDialog(owner);
        }
    
        #endregion
    
        #region IServiceProvider Members
    
        public object GetService(Type serviceType)
        {
            return serviceType == typeof(IWindowsFormsEditorService) ? this : null;
        }
    
        #endregion
    
        #region ITypeDescriptorContext Members
    
        IContainer ITypeDescriptorContext.Container
        {
            get { return null; }
        }
    
        object ITypeDescriptorContext.Instance
        {
            get { return component; }
        }
    
        void ITypeDescriptorContext.OnComponentChanged()
        {}
    
        bool ITypeDescriptorContext.OnComponentChanging()
        {
            return true;
        }
    
        PropertyDescriptor ITypeDescriptorContext.PropertyDescriptor
        {
            get { return property; }
        }
    
        #endregion
    }
    

    【讨论】:

    • 不开玩笑!我开始整理一个样本(我过去做过类似的事情),它很快就失控了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-23
    • 2015-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-18
    相关资源
    最近更新 更多