除了@Marc-Gravell 的回答之外,还有一个库可以轻松获取任何列表的可排序 DGV,因此您可以使用它并调用.ToList()
EF 集合、IQueryables、IEnumerables 等。现在的问题是,如果您使用.ToList()
和排序,数据绑定仍然有效吗?在我所有的测试中,(令我惊讶的是)答案是肯定的(我BindingSource
在 DGV 和数据之间使用 a)。
这是来自 LINQPad 的片段和演示的屏幕截图:
// 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<NOS_MDT_PROJECT>(
// efCollection.ToList());
// var efCollection = context.NOS_MDT_PROJECT.First()
// .NOS_DEFL_TEST_SECT;
// var sortableCollection = new BindingListView<NOS_DEFL_TEST_SECT>(
// 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<NOS_GPR_TST_LOC_DATA>(
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)似乎与BindingSource
在 DGV 和 BLV 之间使用相同,因此您可以使用dgv.DataSource = efCollection
并且仍然获得完整的数据绑定。)
我花了很多时间研究这个问题,并试图理解为什么不能直接对 EF 集合进行排序(或任何集合,就此而言)。以下是有关此问题的许多有用参考资料的链接汇编:
一般数据绑定
一般 DGV 排序和数据绑定
EF 特定
主/详细(又名父/子)视图
如果你想要扩展方法.IsDirty()
,它在 VB 中(需要在具有正确 Imports 语句的模块中):
''' <summary>
''' Determines whether the specified object context has changes from original DB values.
''' </summary>
''' <param name="objectContext">The object context.</param>
''' <returns>
''' <c>true</c> if the specified object context is dirty; otherwise, <c>false</c>.
''' </returns>
<System.Runtime.CompilerServices.Extension()> _
Public Function IsDirty(ByVal objectContext As ObjectContext) As Boolean
Return objectContext.ObjectStateManager.GetObjectStateEntries(
EntityState.Added Or EntityState.Deleted Or EntityState.Modified).Any()
End Function