如何对绑定到EF EntityCollection 的WinForms DataGridView进行排序

我正在尝试将WinForms DataGridView绑定到EntityFramework4对象的EntityCollection 。 麻烦的是,我无法弄清楚如何让它(自动)排序。

我所做的就是将BindingSource的DataSource属性设置为实体的集合。

MyBindingSource.DataSource = CurrentItem.InvoiceNotes;

我真的希望我可以添加一个简单的配置来使它工作; 我真的不想将我的EF Collection包装在一个新的BindingList容器中。

为了支持排序,源需要实现IBindingList并启用排序。 令人讨厌的是,AFAIK唯一内置的类型就是DataView

不过,一切都不会丢失; 您最好的选择是创建数据的BindingList – 或者更确切地说,是Internet上可用的许多BindingList子类之一。 BindingList可以获得90%的方式 – 它只需要大约3(IIRC)个附加方法来实现基本(单列)排序支持。

Dinesh Chandnani在2005年( http://blogs.msdn.com/b/dchandnani/archive/2005/03.aspx )写了一系列文章,它们通过BindingSource很好地解释了绑定。 它是在EF之前编写的,但它提供了一些很好的背景信息。 这是一个小窍门:

当然,您可以直接将DataGridView绑定到DataTable并绕过BindingSource,但BindingSource具有以下优势:

  • 它公开属性以对​​列表进行排序,过滤列表等等,否则这将是一件痛苦的事情。 (即,如果您将DataGridView直接绑定到DataTable,那么要对DataTable进行排序,您需要知道DataTable是一个IListSource,它知道基础列表是DataView,DataView可以进行排序,过滤等)。
  • 如果你必须设置主/子视图,那么BindingSource可以很好地完成这项工作(我在上一篇文章中有更多细节)
  • 隐藏了对DataTable的更改(也在我以前的post中)

再加上@ Marc-Gravell的答案,有一个库可以很容易地为任何列表获得可排序的DGV ,所以你可以使用它,只需在EF集合,IQueryables,IEnumerables等上调用.ToList() 。现在问题是,如果你使用.ToList()和排序,数据绑定仍然有效吗? 在我的所有测试中,(令我惊讶的是)答案是肯定的 (我在DGV和数据之间使用BindingSource )。

这是LINQPad的一个片段和截图到演示:

来自EF集合的可排序数据。在扫描列上按降序排序。

 // http://www.csharpbydesign.com/2009/07/linqbugging---using-linqpad-for-winforms-testing.html void Main() { var context = this; using (var form = new Form()) { var dgv = new DataGridView(); var binder = new BindingSource(); // All of the following variations work // var efCollection = context.NOS_MDT_PROJECT; // var sortableCollection = new BindingListView( // efCollection.ToList()); // var efCollection = context.NOS_MDT_PROJECT.First() // .NOS_DEFL_TEST_SECT; // var sortableCollection = new BindingListView( // efCollection.ToList()); var efCollection = from p in context.NOS_MDT_PROJECT where p.NMP_ID==365 from s in p.NOS_GPR_TST_SECT_COMN_DATA from l in s.NOS_GPR_TST_LOC_DATA select l; var sortableCollection = new BindingListView( efCollection.ToList()); binder.DataSource = sortableCollection; dgv.DataSource = binder; dgv.Dock = DockStyle.Fill; form.Controls.Add(dgv); form.Shown += (o, e) => { dgv.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells); }; form.ShowInTaskbar=true; form.ShowDialog(); if (context.IsDirty()) // Extension method { if (DialogResult.Yes == MessageBox.Show("Save changes?", "", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2)) { context.SaveChanges(); } } } } 

(编辑:将DGV直接绑定到BindingListView (BLV)似乎与使用DGV和BLV之间的BindingSource相同,因此您只需使用dgv.DataSource = efCollection并仍然可以获得完整的数据绑定。)

我花了很多时间研究这个问题,并试图理解为什么你不能只是开箱即用 (或任何集合)对EF集合进行排序 。 以下是有关此问题的许多有用参考资料的链接汇编:

数据绑定一般

  • 幕后花絮:.NET Framework 2.0中对Windows窗体数据绑定的改进,第2部分
  • 详细的数据绑定教程 – CodeProject

DGV分类和数据绑定一般

  • DataGridView使用自定义绑定列表进行排序←CODEcisions
  • c# – 如何实现DataGridView的自动排序? – 堆栈溢出
  • c# – 如何对绑定到自定义对象集合的DataGridView进行排序? – 堆栈溢出
  • 非常非常快速地实现Sortable BindingList – CodeProject

EF具体

  • entity framework数据绑定的快速提示 – Diego Vega – 站点主页 – MSDN博客
  • 显示LINQ to Entities导致DataGridViews并能够排序
  • 在EF实体中使用WPF ObservableCollection – Beth Massi – 分享善意 – 网站首页 – MSDN博客

主/细节(又名父/子)视图

  • WPF中的主 – 详细数据绑定与entity framework – Beth Massi – 分享善意 – 网站首页 – MSDN博客
  • 对绑定到列表框的包含集合进行排序

如果你想要扩展方法.IsDirty() ,这里它在VB中(需要在一个带有正确Imports语句的模块中):

 '''  ''' Determines whether the specified object context has changes from original DB values. '''  ''' The object context. '''  ''' true if the specified object context is dirty; otherwise, false. '''   _ Public Function IsDirty(ByVal objectContext As ObjectContext) As Boolean Return objectContext.ObjectStateManager.GetObjectStateEntries( EntityState.Added Or EntityState.Deleted Or EntityState.Modified).Any() End Function 

谢谢Andrew Davey, 他的博客还有很多有趣的东西。

这里在Vb.net中使用BindingListView(BLV)也很简单:

 Imports Equin.ApplicationFramework Dim elements As List(Of projectDAL.Document) = db.Document.Where( Function(w)w.IdProject = _activeProject.Id).OrderBy(Function(i) i.Description).ToList Dim mySource As BindingListView(Of projectDAL.Document) mySource = New BindingListView(Of projectDAL.Document)(elements)