2009-09-10 16 views
0

我使用C#,Windows窗體,.NET 3.5 SP1的DataGridView與運行時間列

我有很多列,我不知道,直到運行時(即我不要一個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) }); 
} 

回答

1

另一種方法是使用反射。

要設置的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 bool IsNullableType(Type theType) 
{ 
    return (theType.IsGenericType && 
      theType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))); 
} 

要填充的DataGridView:

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