2

さて、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
}

ModuleData オブジェクトと BatchData オブジェクトの両方を記述する項目を含む ListView コントロールがあります。ListView から BatchData 項目を選択すると、予想どおり、PropertyGrid にコレクション エディターが表示されます。コレクション エディターを、ListView コントロールにリストされている ModuleData 項目のみに制限する方法はありますか? 理想的には、(ListView からの) BatchData アイテムを BatchData コレクションに追加したくありません。特に、コレクションは BatchData オブジェクト タイプに対して「型指定」されていないためです。

さらにコード サンプルが必要な場合は、スニペットを編集して喜んで差し上げます。

わかりやすくするために、ModuleData は、指定されたアセンブリ内のクラスをインスタンス化するために必要なデータを保持するカスタム クラスです。含まれているのは、フィールドとパブリック/内部プロパティだけです。私がやりたいことは、プロパティ グリッド コントロールでアセンブルされたコレクション エディターを使用して、ModuleData オブジェクトを BatchDataModuleコレクションに追加することです。追加できる ModuleData オブジェクトは、ListView コントロールに一覧表示されます。

編集:: List<ModuleData>継承を削除しました。

更新: カスタム コレクション エディターを作成する場合、それは独自のカスタム フォーム/ダイアログを作成することを意味しますか? 次に、基本的に、UITypeEditor の属性と継承を通じて、カスタム コレクション ダイアログを表示するための情報をプロパティ グリッドに提供しますか?

4

1 に答える 1

4

まず、これがリストを継承 ( ) し、ラップ ( ) する理由が少しわかりません。どちらでも個別に問題ないはずです。: List<ModuleData>public List<ModuleData> Modules { get { return this; } }

でも!作成できる新しいオブジェクトのタイプを定義するには、プロパティCollectionEditorから派生させてオーバーライドし、このエディターをタイプに関連付ける必要があります。どのオブジェクトを追加可能にしたいのか、またこれが最適な設計かどうかについては、少しわかりません。既存のオブジェクトを追加したい場合は、完全にカスタムのエディター / uitypeeditor が必要になる場合があります。NewItemTypes


更新された質問では、それは間違いなくカスタムの仕事のように聞こえ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;
    }
}
于 2010-02-07T08:45:51.320 に答える