解决DataGridView 控件必须绑定到IBindingList才能排序方法

DataGridView使用List<T>做数据源:

List<Person> people = new List<Person>();
//todo
dataGridView1.DataSource = people;

调用Sort方法排序出错,提示:

引用内容
DataGridView 控件必须绑定到 IBindingList 对象才能排序

我们知道,使用DataTable做数据源时排序是没问题的,所以首先想到的是有没有办法将List<T>转成DataTable?有网友提供了两个扩展方法经测试可行:

public static class DataTableExtensions
{
    /// <summary>
    /// List<T>转DataTable
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="list"></param>
    /// <returns></returns>
    public static DataTable ToDataTable<T>(this List<T> list)
    {
        DataTable result = new DataTable();
        List<PropertyInfo> pList = new List<PropertyInfo>();
        Type type = typeof(T);
        Array.ForEach<PropertyInfo>(type.GetProperties(), prop => { pList.Add(prop); result.Columns.Add(prop.Name, prop.PropertyType); });
        foreach (var item in list)
        {
            DataRow row = result.NewRow();
            pList.ForEach(p => row[p.Name] = p.GetValue(item, null));
            result.Rows.Add(row);
        }
        return result;
    }

    /// <summary>
    /// DataTable转List<T>
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="table"></param>
    /// <returns></returns>
    public static List<T> ToList<T>(this DataTable table) where T : class, new()
    {
        List<T> result = new List<T>();
        List<PropertyInfo> pList = new List<PropertyInfo>();
        Type type = typeof(T);
        Array.ForEach<PropertyInfo>(type.GetProperties(), prop => { if (table.Columns.IndexOf(prop.Name) != -1) pList.Add(prop); });
        foreach (DataRow row in table.Rows)
        {
            T obj = new T();
            pList.ForEach(prop => { if (row[prop.Name] != DBNull.Value) prop.SetValue(obj, row[prop.Name], null); });
            result.Add(obj);
        }
        return result;
    }
}

dataGridView1.DataSource = people.ToDataTable();

另一个思路是根据错误信息实现自己的IBindingList对象,也有网友提供了方法:

/// <summary>
/// 提供支持数据绑定的泛型集合
/// </summary>
/// <typeparam name="T"></typeparam>
public class BindingCollection<T> : BindingList<T>
{
    private bool _isSortedCore = true;
    private ListSortDirection _sortDirectionCore = ListSortDirection.Ascending;
    private PropertyDescriptor _sortPropertyCore = null;

    /// <summary>
    /// 是否已排序
    /// </summary>
    protected override bool IsSortedCore
    {
        get { return _isSortedCore; }
    }
    /// <summary>
    /// 获取列表的排序方向
    /// </summary>
    protected override ListSortDirection SortDirectionCore
    {
        get { return _sortDirectionCore; }
    }
    /// <summary>
    /// 获取用于对列表排序的属性说明符
    /// </summary>
    protected override PropertyDescriptor SortPropertyCore
    {
        get { return _sortPropertyCore; }
    }
    /// <summary>
    /// 是否支持排序
    /// </summary>
    protected override bool SupportsSortingCore
    {
        get { return true; }
    }
    /// <summary>
    /// 是否支持搜索
    /// </summary>
    protected override bool SupportsSearchingCore
    {
        get { return true; }
    }

    /// <summary>
    /// 构造函数
    /// </summary>
    public BindingCollection()
    { }

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="list"></param>
    public BindingCollection(IList<T> list)
        : base(list)
    { }

    /// <summary>
    /// 对项排序
    /// </summary>
    /// <param name="property"></param>
    /// <param name="direction"></param>
    protected override void ApplySortCore(PropertyDescriptor property, ListSortDirection direction)
    {
        List<T> items = this.Items as List<T>;

        if (items != null)
        {
            ObjectPropertyCompare<T> pc = new ObjectPropertyCompare<T>(property, direction);
            items.Sort(pc);
            _isSortedCore = true;
            _sortDirectionCore = direction;
            _sortPropertyCore = property;
        }
        else
        {
            _isSortedCore = false;
        }

        this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
    }

    /// <summary>
    /// 移除排序
    /// </summary>
    protected override void RemoveSortCore()
    {
        _isSortedCore = false;
        this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
    }
}

public class ObjectPropertyCompare<T> : IComparer<T>
{
    /// <summary>
    /// 属性
    /// </summary>
    public PropertyDescriptor Property { get; set; }
    /// <summary>
    /// 排序方向
    /// </summary>
    public ListSortDirection Direction { get; set; }

    /// <summary>
    /// 构造函数
    /// </summary>
    public ObjectPropertyCompare()
    { }

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="property"></param>
    /// <param name="direction"></param>
    public ObjectPropertyCompare(PropertyDescriptor property, ListSortDirection direction)
    {
        Property = property;
        Direction = direction;
    }

    /// <summary>
    /// 比较两个对象
    /// </summary>
    /// <param name="x"></param>
    /// <param name="y"></param>
    /// <returns></returns>
    public int Compare(T x, T y)
    {
        object xValue = x.GetType().GetProperty(Property.Name).GetValue(x, null);
        object yValue = y.GetType().GetProperty(Property.Name).GetValue(y, null);

        int returnValue;

        if (xValue == null && yValue == null)
        {
            returnValue = 0;
        }
        else if (xValue == null)
        {
            returnValue = -1;
        }
        else if (yValue == null)
        {
            returnValue = 1;
        }
        else if (xValue is IComparable)
        {
            returnValue = ((IComparable)xValue).CompareTo(yValue);
        }
        else if (xValue.Equals(yValue))
        {
            returnValue = 0;
        }
        else
        {
            returnValue = xValue.ToString().CompareTo(yValue.ToString());
        }

        if (Direction == ListSortDirection.Ascending)
        {
            return returnValue;
        }
        else
        {
            return returnValue * -1;
        }
    }
}

dataGridView1.DataSource = new BindingCollection<Person>(people);

时间: 2024-10-18 08:00:38

解决DataGridView 控件必须绑定到IBindingList才能排序方法的相关文章

子表与DataGridView控件绑定失败

问题描述 privateBindingManagerBasebm1=null;privatevoidDataScanInForm6_Load(objectsender,EventArgse){stringsqlString1="select*from客户";stringsqlString2="select*from订单";string[]sqlStrings=newstring[]{sqlString1,sqlString2};string[]tableNames=

在Visual Studio 2005的DataGridView控件中加入ComboBox下拉列表框的实现(C#)

datagrid|visual|控件|下拉|下拉列表 虽然在Visual Studio中 DataGridView控件的DataGridViewComboBoxColumn可以实现下拉列表框,但这样的列会在整列中都显示下拉列表框,不太美观,而且还要用代码实现数据绑定.本文介绍一种只在当前编辑单元格中显示下拉列表框的方法,供大家参考. 首先新建一个Windows应用程序,将主窗体重命名为MainForm,在MainForm中加入一个DataGridView控件,命名为dgv_User.如下图所示:

mysql-C# Mysql datagridview控件 列标题中文乱码问题

问题描述 C# Mysql datagridview控件 列标题中文乱码问题 用C#从Mysql中读取数据到datagridview控件中,结果列标题中文乱码,内容没事.代码如下: string commstr = "SELECT Patient_ID as ID,NAME as 姓名,TARGET as 患侧,DIAGNOSIS as 诊断 FROM PatientInfo"; this.data_case.DataSource = DBOperate.DBOperate.selec

datagridview-C#dataGridView控件显示数据自动消失。

问题描述 C#dataGridView控件显示数据自动消失. 我在一个窗口中添加了两个dataGridView控件.但是当我要显示另外一个时,有一个里的就不显示.点击刷新的时候,刷新按钮操作的数据显示,点击查看按钮,刷新里面的数据就消失.两个按钮用到一个数据库的不同视图.谢谢. 解决方案 已解决,是我的一个小疏忽. 解决方案二: C#:在DataGridView控件中显示数据

c#-新手,datagridview控件问题,为什么我这边第一行的数据一直不显示

问题描述 新手,datagridview控件问题,为什么我这边第一行的数据一直不显示 我做了一个签到程序,向datagridview里第一列导入名单后,每签到一个就会在第二列对应地方显示"已签到" 但是现在其他行都可以正常显示,只有第一行数据出不来,请问是为什么? for (int j = 1; j < dataGridView1.Rows.Count; j++) { if (签到触发) { dataGridView1.Rows[j].Cells[1].Value = "

急求!C#用dataGridView控件查询数据库数据出问题

问题描述 privatevoidbutton1_Click(objectsender,EventArgse){stringDatabaseName="orcl";//数据库名stringPassword="tiger";//密码stringUsername="scott";//用户名stringServerIP="127.0.0.1";//服务器地址stringstrConn=@"DataSource=(DESCRI

关于dataGridView控件添加新行的问题

问题描述 我想要在dataGridView控件上添加一个空行,并通过textBox控件来添加数据,当然,dataGridView和textBox都绑定到数据库.不知如何实现,请高手指点. 解决方案 解决方案二://先给控件添加列DataGridView.Columns.Add("指代列的名称","列名");//在给控件添加行,当然有几列,一行就有几个单元格,把要显示的一行数据,放在数组中object[]param={"单元格数据"};//给控件添

在DataGridView控件中加入ComboBox下拉列表框的实现

本文转载:http://www.cnblogs.com/luqingfei/archive/2007/03/28/691372.html   虽然在Visual Studio中 DataGridView控件的DataGridViewComboBoxColumn可以实现下拉列表框,但这样的列会在整列中都显示下拉列表框,不太美观,而且还要用代码实现数据绑定.本文介绍一种只在当前编辑单元格中显示下拉列表框的方法,供大家参考. 首先新建一个Windows应用程序,将主窗体重命名为MainForm,在Ma

如何于DataGridView控件中以跨数据行方式显示数据

datagrid|控件|数据|显示 一般来说,每一个字段的内容会单独显示于DataGridView控件的一个数据行中.问题是,某些字段拥有大量文字数据,我是不是能够让该字段的内容以跨数据行的方式来显示,以便在有限的画面空间中的呈现出更完整的内容呢?答案当然是肯定的. 以图表1所示的执行画面而言,「自传」字段的内容并未单独显示于一个数据行中,而是以横跨数据行的方式,显示在同笔数据列之各字段内容的下方.相关程序代码列示如下: using System;using System.Collections