C# 带有运行时列的DataGridView

C# 带有运行时列的DataGridView,c#,winforms,datagridview,C#,Winforms,Datagridview,我正在使用C#、Windows窗体、.NET3.5SP1 我有一个DataGridView,其中有很多在运行时之前不知道的列(也就是说,在运行时之前我不知道我需要一个Foo列)。为了使数据进出单元,我考虑以下体系结构 我是在正确的轨道上,还是错过了更容易的事情 public interface ICustomColumn { object Format (DataGridView dgv, DataGridViewCellFormattingEventArgs e); void

我正在使用C#、Windows窗体、.NET3.5SP1

我有一个DataGridView,其中有很多在运行时之前不知道的列(也就是说,在运行时之前我不知道我需要一个Foo列)。为了使数据进出单元,我考虑以下体系结构

我是在正确的轨道上,还是错过了更容易的事情

public interface ICustomColumn
{
    object Format (DataGridView dgv, DataGridViewCellFormattingEventArgs e);
    void Validate (DataGridView dgv, DataGridViewCellValidatingEventArgs e);
}

public class CustomDataGridView : DataGridView 
{
    protected override void OnCellFormatting (DataGridViewCellFormattingEventArgs e)
    {
        ICustomColumn col = Columns [e.ColumnIndex].Tag as ICustomColumn;
        if ( col != null )
            e.Value = col.Format (this, e);

        base.OnCellFormatting (e);
    }

    protected override void OnCellValidating (DataGridViewCellValidatingEventArgs e)
    {
        ICustomColumn col = Columns [e.ColumnIndex].Tag as ICustomColumn;
        if ( col != null )
            col.Validate (this, e);

        base.OnCellValidating (e);
    }
}

class FooColumn : ICustomColumn
{
    public FooColumn (Dictionary <RowData, Foo> fooDictionary) 
        { this.FooDictionary = fooDictionary; }

    // Foo has a meaningful conversion to the column type (e.g. ToString () for a text column
    protected object Format (DGV dgv, DGVCFEA e)
        { return FooDictionary [(RowData) dgv.Rows[e.RowIndex].DataBoundItem]; }

    // Foo has a meaningful way to interpret e.FormattedValue
    void Validate (DGV dgv, DGVCVEA e)
        { FooDictionary [(RowData) dgv.Rows[e.RowIndex].DataBoundItem].Validate (e.FormattedValue); }
}

void CreateFooColumn (DataGridView dgv)
{
    dgv.Columns.Add (new DataGridViewTextBoxColumn () { Tag = new FooColumn (fooDictionary) });
}
公共接口ICustomColumn
{
对象格式(DataGridView dgv、DataGridViewCellFormattingEventArgs e);
无效验证(DataGridView dgv、DataGridViewCellValidatingEventArgs e);
}
公共类CustomDataGridView:DataGridView
{
受保护的重写void OnCellFormatting(DataGridViewCellFormattingEventArgs e)
{
ICustomColumn coln=Columns[e.ColumnIndex]。标记为ICustomColumn;
如果(列!=null)
e、 值=列格式(此,e);
base.oncell格式(e);
}
受保护的覆盖void OnCellValidating(DataGridViewCellValidatingEventArgs e)
{
ICustomColumn coln=Columns[e.ColumnIndex]。标记为ICustomColumn;
如果(列!=null)
col.Validate(本,e);
base.oncell(e);
}
}
类FooColumn:ICustomColumn
{
公共FooColumn(字典fooDictionary)
{this.foodirectionary=foodirectionary;}
//Foo对列类型进行了有意义的转换(例如,文本列的ToString()
受保护对象格式(DGV DGV、DGVCE)
{return foodirectionary[(RowData)dgv.Rows[e.RowIndex].DataBoundItem];}
//Foo有一种有意义的方法来解释e.FormattedValue
无效验证(DGV DGV、DGVCVEA e)
{FooDictionary[(RowData)dgv.Rows[e.RowIndex].DataBoundItem].Validate(e.FormattedValue);}
}
void CreateFooColumn(DataGridView dgv)
{
dgv.Columns.Add(newdatagridviewtextboxcolumn(){Tag=newfoocolumn(foodirectionary)});
}

另一种方法是使用反射

要设置DataGridView,请执行以下操作:

private void SetUpDataGridView()
{
    // Create the columns based on the data in the album info - get by reflection
    var ai = new AlbumInfo();
    Type t = ai.GetType();

    dataTable.TableName = t.Name;

    foreach (PropertyInfo p in t.GetProperties())
    {
        var columnSpec = new DataColumn();
        // If nullable get the underlying type
        Type propertyType = p.PropertyType;
        if (IsNullableType(propertyType))
        {
            var nc = new NullableConverter(propertyType);
            propertyType = nc.UnderlyingType;
        }
        columnSpec.DataType = propertyType;
        columnSpec.ColumnName = p.Name;
        dataTable.Columns.Add(columnSpec);
    }
}
private void AddToGrid(AlbumInfo info)
{
    // Add album info to table - add by reflection
    Type t = info.GetType();
    var row = new object[t.GetProperties().Length];

    int index = 0;
    foreach (PropertyInfo p in t.GetProperties())
    {
        row[index++] = p.GetValue(info, null);
    }

    dataTable.Rows.Add(row);
    dataGridView.ClearSelection();
}
助手方法:

private bool IsNullableType(Type theType)
{
    return (theType.IsGenericType &&
            theType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)));
}