DataGridView List <t>列?</t>

时间:2010-08-17 19:46:35

标签: c# list collections datagridview

我有一个绑定到List的datagridView。此List由我的类组成,其中包含2个公共属性,一个String Name和另一个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列,并显示类似“Collection”的内容,其中显示“...”按钮,以及点击它时弹出“Collection Editor”

有谁知道这是否可行以及如何启用它?如果有一个教程或任何可以帮助我的东西,我也会感激。谢谢。

4 个答案:

答案 0 :(得分:2)

我认为使用泛型是一个干净的解决方案:

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();
}

答案 1 :(得分:1)

简答:是的,你可以用一些代码来完成。

答案很长:编写代码会让人痛苦,因为您不仅要知道DataGridView在自定义列中的行为,还需要知道如何在运行时公开设计时元素,这需要相当多的管道。还必须了解有关PropertyGrid的广泛知识。

注意:这可能是一个有趣的组件。 (如果我有时间的话,我可能会解决这个问题)

答案 2 :(得分:1)

所以使用Dave发布的'button'方法,以及我发现的一些实现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中添加TabPages ...通过显示“...”按钮......但这可能现在有效。

答案 3 :(得分:0)

您要做的是添加一个带有按钮的列模板:

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

在按钮的处理程序中,从集合中获取所选的MyClass项,并将其list属性绑定到弹出窗口中的网格。