C#语言中对象数组到DataTable的转换

今天在开发工作中遇到了一个问题:

我的很多DataGridView,因为数据源(DataSource)使用的是数组,导致在点击每列列头的时候无法就指定列进行排序

因此我需要写一个将数组转换为DataTable的函数。

在网上查了一下,找到了这篇Blog,总结得比较全面:

http://blog.csdn.net/emoonight/article/details/6617683

不过这篇Blog中,从数组转换成DataTable的函数(函数ToDataTable<T>)有一个BUG,在创建每个数据行的时候,没有对list的元素进行判空操作。这样做在数组中有元素为空时,会导致TargetException,更有甚者如果把这段代码运用到Load函数的时候,有可能函数直接中断执行且不弹出任何异常。

下面是我改造之后的代码(需要引用System.Reflection):

public static class DataHelper
{
    public static DataTable GetDataTable<T>(this IEnumerable<T> list)
    {
        DataTable dtResult = new DataTable();
        List<PropertyInfo> propertiyInfos = new List<PropertyInfo>();
        //生成各列
        Array.ForEach<PropertyInfo>(typeof(T).GetProperties(), p =>
            {
                propertiyInfos.Add(p);
                dtResult.Columns.Add(p.Name, p.PropertyType);
            });
        //生成各行
        foreach (var item in list)
        {
            if (item == null)
            {
                continue;
            }
            DataRow dataRow = dtResult.NewRow();
            propertiyInfos.ForEach(p => dataRow[p.Name] = p.GetValue(item, null));
            dtResult.Rows.Add(dataRow);
        }
        return dtResult;
    }
}

我写了个例子,做了以下测试。

建立一个Windows窗体应用程序,工程名为Array2DataTable

C#语言中对象数组到DataTable的转换_第1张图片

建立一个类Hero,里面有五个属性:

public class Hero
{
    public Hero(int id, string name, int strength, int dexterity, int intelligence)
    {
        this.idField = id;
        this.nameField = name;
        this.strengthField = strength;
        this.dexterityField = dexterity;
        this.intelligenceField = intelligence;
    }

    private int idField;
    public int id
    {
        get
        {
            return idField;
        }
        set
        {
            idField = value;
        }
    }

    private string nameField;
    public string name
    {
        get
        {
            return nameField;
        }
        set
        {
            nameField = value;
        }
    }

    private int strengthField;
    public int strength
    {
        get
        {
            return strengthField;
        }
        set
        {
            strengthField = value;
        }
    }

    private int dexterityField;
    public int dexterity
    {
        get
        {
            return dexterityField;
        }
        set
        {
            dexterityField = value;
        }
    }

    private int intelligenceField;
    public int intelligence
    {
        get
        {
            return intelligenceField;
        }
        set
        {
            intelligenceField = value;
        }
    }
}

在FormMain中的Load函数中加入下面代码:

private void FormMain_Load(object sender, EventArgs e)
{
    Hero[] heros = new Hero[10];
    heros[0] = new Hero(1, "秃驴", 59, 64, 78);
    heros[1] = new Hero(2, "独眼龙", 96, 99, 94);
    heros[2] = new Hero(3, "三脚猫", 50, 88, 73);
    heros[3] = new Hero(4, "绿帽王八", 79, 77, 61);
    heros[4] = new Hero(5, "四眼田鸡", 89, 93, 63);
    heros[5] = new Hero(6, "地头蛇", 71, 70, 58);
    heros[6] = new Hero(7, "单身狗", 95, 82, 89);
    heros[7] = new Hero(8, "替罪羊", 90, 81, 93);
    heros[8] = new Hero(9, "黄牛", 81, 52, 67);
    dgvArray.DataSource = heros;

    dgvDataTable.DataSource = DataHelper.GetDataTable<Hero>(heros);
}

程序运行后的效果如下,可以看到,以DataTable为数据源的DataGridView(dgvDataTable),已经可以点击列首进行排序了:

C#语言中对象数组到DataTable的转换_第2张图片

如果希望某几列可以排序,某几列不可以排序,可以手动将这些列的信息添加到DataGridView的列中,并配置好DataPropertyName,最后在“编辑列”中设置“SortMode”属性,该属性的值为System.Windows.Forms.DataGridViewColumnSortMode 类型枚举。这个枚举下有三个值,现将三者列在下面,其中的说明信息摘自VS中反射到的元数据:

1)DataGridViewColumnSortMode.NotSortable

  -此列仅能以编程方式进行排序,但由于它原本并不打算排序,所以列标头将不包含排序标志符号的空间

2)DataGridViewColumnSortMode.Automatic

  -除非列标头用于进行选择,否则用户可以通过单击列标头对列进行排序。 排序标志符号将自动显示出来

3)DataGridViewColumnSortMode.Programmatic

  -此列仅能以编程方式进行排序,并且列标头将包含排序标志符号的空间

这个设置的默认值都是DataGridViewColumnSortMode.Automatic

END

你可能感兴趣的:(排序,转换,Datatable,datagridview,对象数组)