Вопрос

Хорошо, я прочитал пару вопросов, касающихся использования PropertyGrid и коллекций.Но мне трудно понять, как / если [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.Когда я выбираю элемент BatchData из ListView, PropertyGrid, как и ожидалось, отображает редактор коллекции.Есть ли способ ограничить редактор коллекций любыми элементами ModuleData, перечисленными только в элементе управления ListView?В идеале я бы не хотел, чтобы элемент BatchData (из ListView) добавлялся в коллекцию BatchData, тем более что коллекция не "типизирована" для типов объектов BatchData.

Если будут запрошены какие-либо дополнительные образцы кода, я буду более чем счастлив отредактировать некоторые фрагменты.

Для наглядности ModuleData - это пользовательский класс, который содержит данные, необходимые для создания экземпляра класса в указанной сборке.Все, что он содержит, - это поля и общедоступные / внутренние свойства.Что я хотел бы сделать, так это использовать редактор коллекций, собранный с помощью элемента управления property grid, для добавления объектов ModuleData в BatchData Module Коллекция.Объекты ModuleData, которые могут быть добавлены, перечислены в элементе управления ListView.

Редактировать:Удалил : List<ModuleData> наследование.

Обновить:Если я собираюсь создать пользовательский редактор коллекций, означает ли это, что я создаю свою собственную пользовательскую форму / диалоговое окно?Затем, в основном предоставляя propertygrid информацию для отображения моего пользовательского диалогового окна коллекции через атрибуты и наследование UITypeEditor?

Это было полезно?

Решение

Во-первых, я маленький не уверен в том, почему это оба наследует (: List<ModuleData>) и обертывания (public List<ModuleData> Modules { get { return this; } }) список - либо по отдельности должно быть в порядке.

Однако!Чтобы определить типы новых объектов, которые вы можете создавать, вам необходимо вывести из CollectionEditor и переопределить NewItemTypes свойство - и ассоциируй этот редактор с твоим типом.Я - это маленький немного неясно, какие объекты вы хотите добавить, и является ли это лучшим дизайном.Если вы хотите добавить существующий объекты вам может понадобиться полностью пользовательский редактор / 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;
    }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top