代码之家  ›  专栏  ›  技术社区  ›  IAbstract

如何将PropertyGrid集合限制为列表<T>

  •  2
  • IAbstract  · 技术社区  · 16 年前

    好的,我已经阅读了几个关于PropertyGrid和collections使用的问题。但是,我很难理解如何/如果 [TypeConverter] 这对我有用。我读过MSDN发布的小广告,坦率地说,对于这个可怜的自学成才的程序员来说,这有点欠缺。

    所以,这就是我所拥有的。首先是收集:

    [Serializable]
    public List<ModuleData> Modules
    { get { return modules; } }
    
    private List<ModuleData> modules;
    

    [Serializable]
    internal class ModuleData : IEquatable<ModuleData>
    {
        // simple data class with public properties
        // to display in the propgrid control
    }
    

    我有一个ListView控件,其中包含描述ModuleData对象和BatchData对象的项。当我从ListView中选择BatchData项时,PropertyGrid(如预期的那样)将显示集合编辑器。是否有办法将集合编辑器限制为仅在ListView控件中列出的任何ModuleData项?理想情况下,我不希望将BatchData项(来自ListView)添加到BatchData集合中,尤其是因为该集合不是BatchData对象类型的“类型化”集合。

    为清楚起见,ModuleData是一个自定义类,它保存在指定程序集中实例化类所需的数据。它只包含字段和公共/内部属性。我想做的是使用与属性网格控件组合的集合编辑器将ModuleData对象添加到BatchData Module 收集可以添加的ModuleData对象列在ListView控件中。

    编辑:删除了 : List<ModuleData>

    更新:如果我要创建自定义集合编辑器,这是否意味着我要构建自己的自定义表单/对话框?然后基本上通过UITypeEditor的属性和继承向propertygrid提供显示自定义集合对话框的信息?

    1 回复  |  直到 16 年前
        1
  •  4
  •   Marc Gravell    16 年前

    首先,我是一个 不确定为什么这两者都会继承( : List<ModuleData> )包装( public List<ModuleData> Modules { get { return this; } } )一份清单——可以单独列出。

    CollectionEditor 并覆盖 NewItemTypes property -并将此编辑器与您的类型关联。我是一名医生 小的 现有的 对象您可能需要一个完全自定义的编辑器/uitypeeditor。


    UITypeEditor ; 这是一个使用下拉菜单的版本;您也可以使用弹出窗口(请参见上的方法) svc ):

    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Drawing.Design;
    using System.Windows.Forms;
    using System.Windows.Forms.Design;
    using System.Collections;
    
    static class Program
    {
        static void Main()
        {
            MyWrapper wrapper = new MyWrapper();
            wrapper.Modules.Add(new ModuleData { ModuleId = 123 });
            wrapper.Modules.Add(new ModuleData { ModuleId = 456 });
            wrapper.Modules.Add(new ModuleData { ModuleId = 789 });
    
            wrapper.Batches.Add(new BatchData(wrapper) { BatchId = 666 });
            wrapper.Batches.Add(new BatchData(wrapper) { BatchId = 777 });
    
            PropertyGrid props = new PropertyGrid { Dock = DockStyle.Fill };
            ListView view = new ListView { Dock = DockStyle.Left };
            foreach (ModuleData mod in wrapper.Modules) {
                view.Items.Add(mod.ToString()).Tag = mod;
            }
            foreach (BatchData bat in wrapper.Batches) {
                view.Items.Add(bat.ToString()).Tag = bat;
            }
            view.SelectedIndexChanged += delegate {
                var sel = view.SelectedIndices;
                if(sel.Count > 0) {
                    props.SelectedObject = view.Items[sel[0]].Tag;
                }
            };
    
            Application.Run(new Form { Controls = { props, view} });
        }
    }
    
    class MyWrapper
    {
        private List<ModuleData> modules = new List<ModuleData>();
        public List<ModuleData> Modules { get { return modules; } }
    
        private List<BatchData> batches = new List<BatchData>();
        public List<BatchData> Batches { get { return batches; } }
    }
    
    class ModuleListEditor : UITypeEditor
    {
        public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
        {
             return UITypeEditorEditStyle.DropDown;
        }
        public override object  EditValue(ITypeDescriptorContext context, System.IServiceProvider provider, object value)
        {
            IWindowsFormsEditorService svc;
            IHasModules mods;
            IList selectedModules;
            if (context == null || (selectedModules = (IList)value) == null ||
                (mods = context.Instance as IHasModules) == null
                || (svc = (IWindowsFormsEditorService)
                provider.GetService(typeof(IWindowsFormsEditorService))) == null)
            {
                return value;
            }
            var available = mods.GetAvailableModules();
            CheckedListBox chk = new CheckedListBox();
            foreach(object item in available) {
                bool selected = selectedModules.Contains(item);
                chk.Items.Add(item, selected);
            }
            chk.ItemCheck += (s, a) =>
            {
                switch(a.NewValue) {
                    case CheckState.Checked:
                        selectedModules.Add(chk.Items[a.Index]);
                        break;
                    case CheckState.Unchecked:
                        selectedModules.Remove(chk.Items[a.Index]);
                        break;
                }
            };
    
    
            svc.DropDownControl(chk);
    
            return value;
        }
        public override bool IsDropDownResizable {
            get {
                return true;
            }
        }
    }
    
    
    interface IHasModules
    {
        ModuleData[] GetAvailableModules();
    }
    
    internal class BatchData : IHasModules {
        private MyWrapper wrapper;
        public BatchData(MyWrapper wrapper) {
            this.wrapper = wrapper;
        }
        ModuleData[] IHasModules.GetAvailableModules() { return wrapper.Modules.ToArray(); }
        [DisplayName("Batch ID")]
        public int BatchId { get; set; }
        private List<ModuleData> modules = new List<ModuleData>();
        [Editor(typeof(ModuleListEditor), typeof(UITypeEditor))]
        public List<ModuleData> Modules { get { return modules; } set { modules = value; } }
    
        public override string ToString() {
            return "Batch " + BatchId;
        }
    }
    
    internal class ModuleData {
        [DisplayName("Module ID")]
        public int ModuleId { get; set; }
    
        public override string ToString() {
            return "Module " + ModuleId;
        }
    }