簡體   English   中英

DataGridView列表 <T> 柱?

[英]DataGridView List<T> column?

我有一個datagridView,它綁定到一個列表。 該列表由我的類組成,該類包含2個公共屬性,一個字符串名稱和另一個List CustomList。 見下文:

public class MyClass2
{        
    public string Name
    { get; set;}


    public string Description
    {
        get;
        set;
    }
}

public class MyClass
{
    List<MyClass2> myList;

    public string Name
    {
        get;
        set;
    }

    public List<MyClass2> CustomList
    {
        get { return myList ?? (myList= new List<MyClass2>()); }
    }

}

然后在我的設計器頁面中:

List<MyClass> myClassList = new List<MyClass>();
dataGridView.DataSource = myClassList;

現在,網格中唯一出現的列是MyClass:Name列,而CustomList列未顯示。 我想要的是CustomList列,它顯示並顯示類似“集合”的內容,並帶有“ ...”按鈕,單擊該按鈕可彈出“集合編輯器”。

有誰知道這是否可能以及如何啟用它? 如果有一個教程或任何可以幫助我的東西,我也將不勝感激。 謝謝。

我認為使用泛型是一個干凈的解決方案:

public class Sorter<T>: IComparer<T>
{
    public string Propiedad { get; set; }

    public Sorter(string propiedad)
    {
        this.Propiedad = propiedad;
    }

    public int Compare(T x, T y)
    {
        PropertyInfo property = x.GetType().GetProperty(this.Propiedad);
        if (property == null)
            throw new ApplicationException("El objeto no tiene la propiedad " + this.Propiedad);
        return Comparer.DefaultInvariant.Compare(property.GetValue(x, null), property.GetValue(y, null));
    }
}

用法示例:

string orderBy = "propertyName";
bool orderAsc = true;

List<MyExampleClass> myClassList = someMethod();

if (!string.IsNullOrEmpty(orderBy))
{
    myClassList.Sort(new Sorter<MyExampleClass>(orderBy));
    if (!orderAsc) myClassList.Reverse();
}

簡短的回答:是的,您可以使用一些代碼來完成。

長答案:編寫代碼會很麻煩,因為您不僅必須知道DataGridView如何與自定義列一起工作,而且還需要知道如何在運行時公開設計時元素,這需要有點水暖。 還必須了解有關PropertyGrid的廣泛知識。

注意:這可能是一個有趣的組件。 (如果有時間,我可能會解決)

因此,使用Dave發布的“按鈕”方法以及我發現的一些實現CollectionEditor的代碼,我可以在MyClass2中編輯CustomList

這是我的解決方案,盡管不盡如人意:

將此類放在某處:

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

將按鈕列添加到數據網格:

DataGridViewButtonColumn butt = new DataGridViewButtonColumn();
butt.HeaderText = "CustomList";
butt.Name = "CustomList";
butt.Text = "Edit CustomList...";
butt.UseColumnTextForButtonValue = true;

dataGridView.Columns.Add(butt);
dataGridView.CellClick += new DataGridViewCellEventHandler(dataGridView_CellClick);

然后在單元格單擊的按鈕處理程序中調用它。

if (e.RowIndex < 0 || e.ColumnIndex != dataGridView.Columns["CustomList"].Index)
            return;

//get the name of this column
string name = (string)dataGridView[dataGridView.Columns["Name"].Index, e.RowIndex].Value;

var myClassObject= myClassList.Find(o => o.Name == name);

MyHelper.EditValue(this, myClassObject, "CustomList");

我仍然對聽到其他方法感興趣,而不必實現自己的CollectionEditor。 而且,我仍然對使它看起來更像TabControl用來在PropertyGrid中添加TabPage的方式感興趣……通過顯示“ ...”按鈕……但這暫時可能有效。

您要做的是添加一個帶有按鈕的列模板:

http://geekswithblogs.net/carmelhl/archive/2008/11/11/126942.aspx

在按鈕的處理程序中,從集合中獲取選定的MyClass項,並將其list屬性綁定到彈出窗口中的網格。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM