J’essaie de lier un WinForms DataGridView à un EntityCollection
partir d’un object EntityFramework4. Le problème, c’est que je ne vois pas comment le faire sortinger (automatiquement).
Je ne fais que définir la propriété DataSource de BindingSource sur la collection de l’entité.
MyBindingSource.DataSource = CurrentItem.InvoiceNotes;
J’espère vraiment qu’il y a une configuration simple à append pour que cela fonctionne; Je ne veux vraiment pas avoir à emballer ma collection EF dans un nouveau conteneur BindingList.
Pour prendre en charge le sorting, la source doit implémenter IBindingList
avec le sorting activé. Ce qui est ennuyeux, c’est que DataView
est le seul type intégré à cela.
Cependant tout n’est pas perdu; Votre meilleure option est de créer une BindingList
de vos données – ou plutôt l’une des nombreuses sous-classes BindingList
disponibles à titre d’exemple sur Internet. BindingList
vous BindingList
90% du chemin. Il suffit d’environ 3 méthodes supplémentaires (IIRC) à implémenter pour obtenir une prise en charge de base du sorting (une colonne).
Dinesh Chandnani a écrit une série d’articles en 2005 ( http://blogs.msdn.com/b/dchandnani/archive/2005/03.aspx ) qui expliquent bien la liaison via BindingSource. Il a été écrit avant EF, mais il fournit de bonnes informations de base. Voici une friandise:
Bien sûr, vous pouvez lier directement DataGridView à DataTable et contourner BindingSource, mais BindingSource présente certains avantages:
- Il expose les propriétés pour sortinger la liste, filtrer la liste, etc., ce qui serait autrement difficile à faire. (Par exemple, si vous liez le DataGridView au DataTable directement, pour sortinger le DataTable, vous devez savoir que DataTable est un IListSource qui connaît la liste sous-jacente qui est un DataView et un DataView peut être sortingé, filtré, etc.).
- Si vous devez configurer des vues maître / enfant, BindingSource fait un excellent travail en ce sens (plus de détails dans mon précédent post)
- Les modifications apscopes au DataTable sont masquées (également dans mon précédent post)
En plus de la réponse de @ Marc-Gravell, il existe une bibliothèque qui facilite l’obtention de fichiers DGV sortingables pour toute liste . Vous pouvez donc l’utiliser et appeler simplement .ToList()
sur des collections EF, IQueryables, IEnumerables, etc. Maintenant, la question Si vous utilisez .ToList()
et que vous sortingez, la liaison de données fonctionnera-t-elle encore? Dans tous mes tests, la réponse (surprenante, pour moi) est oui (j’utilise un BindingSource
entre le DGV et les données).
Voici un extrait de LINQPad et une capture d’écran pour une démonstration:
// 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(); } } } }
(EDIT: La liaison du BindingListView
DGV directement à BindingListView
(BLV) semble fonctionner de la même manière que l’utilisation du BindingSource
entre le BindingSource
DGV et le BindingSource
BLV. Vous pouvez donc simplement utiliser dgv.DataSource = efCollection
et obtenir une dgv.DataSource = efCollection
complète.)
J’ai passé beaucoup de temps à étudier cette question et à essayer de comprendre pourquoi vous ne pouvez pas simplement sortinger une collection EF prête à l’emploi (ou toute collection, d’ailleurs). Voici une compilation de liens vers de nombreuses références utiles concernant cette question:
Et si vous voulez la méthode d’extension .IsDirty()
, la voici en VB (doit être dans un module avec les instructions Imports correctes):
''' ''' 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.GetObjectStateEnsortinges( EntityState.Added Or EntityState.Deleted Or EntityState.Modified).Any() End Function
Merci Andrew Davey, son blog a beaucoup d’autres choses intéressantes.
Voici une utilisation simple de BindingListView (BLV) dans Vb.net qui fonctionne aussi:
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)