【问题标题】:How to sort DataGridView when bound to a binding source that is linked to an EF4 Entity绑定到链接到 EF4 实体的绑定源时如何对 DataGridView 进行排序
【发布时间】:2011-05-26 16:44:43
【问题描述】:

我有一个链接到 BindingSourceDataGridView

我的BindingSource 链接到IQueryable 实体列表:

    public void BindTo(IQueryable elements)
    {
        BindingSource source = new BindingSource();
        source.DataSource = elements;

        bindingNavigator1.BindingSource = source;
        dataGridView1.DataSource = source;

    }

我希望我的用户能够单击网格标题来对数据进行排序 - 努力让它发挥作用。可能吗?如果是这样,我该怎么做?

【问题讨论】:

  • 注意:DataGridView 似乎是 WindowsForms,而不是 WPF。仅适用于也希望为其 WPF DataGrid 排序问题找到解决方案的人。

标签: c# winforms entity-framework sorting datagridview


【解决方案1】:

我最近也遇到了同样的问题;似乎 IQueryable 接口没有为 DataViewGrid 提供足够的信息来了解如何自动对数据进行排序;所以你必须要么使用它可以使用的东西从实体源重新打包你的集合,要么做我所做的并手动处理排序功能:

      private void myDataGridView_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
  {
     DataGridViewColumn column = myDataGridView.Columns[e.ColumnIndex];

     _isSortAscending = (_sortColumn == null || _isSortAscending == false);

     string direction = _isSortAscending ? "ASC" : "DESC";

     myBindingSource.DataSource = _context.MyEntities.OrderBy(
        string.Format("it.{0} {1}", column.DataPropertyName, direction)).ToList();

     if (_sortColumn != null) _sortColumn.HeaderCell.SortGlyphDirection = SortOrder.None;
     column.HeaderCell.SortGlyphDirection = _isSortAscending ? SortOrder.Ascending : SortOrder.Descending;
     _sortColumn = column;
  }

希望对你有帮助。

【讨论】:

  • 有没有办法在允许更新的同时做到这一点?如果使用 ToList(),则只能写入临时列表,如果不使用 ToList,如果绑定到 IOrderedEnumerable,DataGridView 似乎禁用添加记录...
  • 我意识到我需要调用 ObjectQuery.OrderBy,而不是 IEnumerable.OrderBy 来维护可更新的绑定。
【解决方案2】:

VB.NET

如果您使用的是带有 linq 语法的绑定源,您可以像这样对数据进行排序

在这种情况下,当从实体框架对象“NCFile”加载与 datagridview 关联的绑定源时,具有外部列到“NCFilePartSet”列表中

bsFileSections.DataSource = From ncfps In NCFile.NCFilePartSet Order By ncfps.Sort Select ncfps 

或者像这样

bsFileSections.DataSource = NCFile.NCFilePartSet.OrderBy(Function(ncfps) ncfps.Sort)

其中“排序”是 NCFilePartSet 中的一列

实体的更新继续工作并反映回数据库

【讨论】:

  • OP 想要“[让]我的用户……点击网格标题对数据进行排序。”如果您对排序列进行硬编码,则您的答案有效,但是当用户想要更改排序列并且不丢失她/他已经编辑/添加的任何数据时,您如何处理数据绑定?我认为这才是真正的挑战。
【解决方案3】:

是的,当绑定到 EF 数据时,可以轻松拥有可排序的 DGV。使用BLW library 中的BindingListView(也可以查看How do I implement automatic sorting of DataGridView?)。

public void BindTo(IQueryable elements)
{
    BindingSource source = new BindingSource();
    source.DataSource = new BindingListView(elements.ToList());

    bindingNavigator1.BindingSource = source;
    dataGridView1.DataSource = source;

}

在我的测试中,即使在构造函数中调用.ToList()(如上),更改也会传播到数据库,这让我很惊讶。

【讨论】:

    【解决方案4】:

    这段代码 sn-p 运行良好,并且对于大多数用途来说足够快...

    int iColNumber = 3; //e.g., sorting on the 3rd column of the DGV
    
    MyBindingSource.DataSource = MyBindingList.OrderByDescending(o => o.GetType().GetProperty(MyDataGridView.Columns[iColNumber].Name).GetValue(o));
    

    【讨论】:

      【解决方案5】:

      我建议您将实体动态转换为数据表。有一种方法

       public static DataTable GetTableFromList<T>(IEnumerable<T> list)
          {
              DataTable dt = new DataTable();
              PropertyInfo[] properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
      
              foreach (PropertyInfo property in properties)
                  dt.Columns.Add(property.Name, property.PropertyType);
      
              foreach (T item in list)
              {
                  DataRow newRow = dt.NewRow();
                  foreach (PropertyInfo property in properties)
                  {
                      newRow[property.Name] = property.GetValue(item);
                  }
                      dt.Rows.Add(newRow);
              }
      
              return dt;
          }
      

      将表转换为绑定源后

      source.DataSource = GetTableFromList<T>(elements);
      

      注意不能转换为列类型的属性类型。

      【讨论】:

        【解决方案6】:

        也许这会对你有所帮助。

        internal class CustomDataGridView : DataGridView
        {   
            public SortOrder MySortOrder { get; set; }
            protected override void OnColumnHeaderMouseClick(DataGridViewCellMouseEventArgs e)
            {
                BindingSource MyBindingSource = (BindingSource)base.DataSource;
                DataTable MyDataTable = (DataTable)MyBindingSource.DataSource;
                switch (MySortOrder)
                {
                    case SortOrder.None:
                        MyDataTable.DefaultView.Sort = base.Columns[e.ColumnIndex].Name + " ASC";
                        MyDataTable = MyDataTable.DefaultView.ToTable();
                        MyBindingSource.DataSource = MyDataTable;
                        MySortOrder = SortOrder.Ascending;
                        break;
        
                    case SortOrder.Ascending:
                        MyDataTable.DefaultView.Sort = base.Columns[e.ColumnIndex].Name + " DESC";
                        MyDataTable = MyDataTable.DefaultView.ToTable();
                        MyBindingSource.DataSource = MyDataTable;
                        MySortOrder = SortOrder.Descending;
                        break;
        
                    case SortOrder.Descending:
                        MyDataTable.DefaultView.Sort = Properties.Settings.Default.OderDataGridView; //SqlOriginOrder
                        MyDataTable = MyDataTable.DefaultView.ToTable();
                        MyBindingSource.DataSource = MyDataTable;
                        MySortOrder = SortOrder.None;
                        break;
                }
                base.Columns[e.ColumnIndex].HeaderCell.SortGlyphDirection = MySortOrder; //mini arrow 
            }
        }
        

        【讨论】:

        • 不,这没有帮助。 DataTable 与IQueryable 完全不同。 (顺便说一句,你把案子弄混了)。
        • 确保 DataTable 必须保留在其 DatagridView 中:需要软件维护。我应该指定它吗?
        • 只要你在谈论 DataTable 这与问题无关。
        • 很难觉醒,在法国他们被称为“龙雄”。但是,您是对的;我的对象与本节无关。擦除或移动它!
        猜你喜欢
        • 2014-07-07
        • 1970-01-01
        • 2011-06-21
        • 2012-03-30
        • 2011-08-19
        • 1970-01-01
        • 2017-09-20
        • 2022-01-23
        • 2010-11-26
        相关资源
        最近更新 更多