2010-02-07 58 views
2

好吧,我已閱讀了有關使用PropertyGrid和集合的幾個問題。但是,我很難理解如何/如果[TypeConverter]會爲我工作。我已經讀過MSDN推出的那個小小的年代,坦率地說,這個可憐的,自學成才的程序員有點缺乏。如何將PropertyGrid集合限制爲列表<T>

所以,這裏是我的。首先集合:

[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項目?理想情況下,我不希望將BatchData項(來自ListView)添加到BatchData集合中 - 尤其是因爲該集合不是針對BatchData對象類型的「類型」。

如果要求任何進一步的代碼示例,我會更樂意在編輯一些片斷。

爲清楚起見,ModuleData是持有指定的組件中需要實例類數據的自定義類。它包含的所有字段和公共/內部屬性。我想要做的是使用與屬性網格控件組裝的集合編輯器將ModuleData對象添加到BatchData Module集合中。 ListView控件中列出了有資格添加的ModuleData對象。

編輯:刪除了: List<ModuleData>繼承。

更新:如果我要創建自定義集合編輯器,這是否意味着我正在構建自己的自定義窗體/對話框?然後基本上提供propertygrid的信息來顯示我的自定義集合對話框通過UITypeEditor的屬性和繼承?

+0

我試着補充一些想法,但我仍然什麼* *究竟要發生很模糊。 – 2010-02-07 08:47:11

+0

@馬克 - 編輯,希望澄清一些。 – IAbstract 2010-02-08 03:49:56

+0

@Marc - 爲了完成我的任務,我想我必須改變這個問題,這不會是猶太教(根據我已經閱讀的meta)。所以,我會接受你的回答 - 我不喜歡鬆散的結局。;)它確實幫助我研究不同的途徑,所以這是一個可行的答案! – IAbstract 2010-02-08 05:27:50

回答

4

首先我是不確定爲什麼這兩者都繼承(: 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; 
    } 
} 
+0

我的整個評論剛剛離開。 :(好吧,再來一次...我有屬性'return this;'因爲我看不到'propgrid.SelectedObject = myBatchData'中的集合。我會在睡覺之後檢查明天的鏈接它!Thx !!! – IAbstract 2010-02-07 09:28:54

+0

@Marc:OMG ...你確定你沒有扮演Jon Skeet,並且在問題寫出之前寫回答嗎?LOL ...這回答了......這個問題......會有一直...... – IAbstract 2010-02-08 06:32:28

+0

並且我可以加...你超越了這個範圍,並且非常感謝...... – IAbstract 2010-02-08 06:34:26

相關問題