C #: sorting personnalisé de DataGridView

Je dois sortinger un DataGridView avec un sorting naturel (comme dans l’Explorateur) pour que les nombres et le texte (dans la même colonne) soient sortingés naturellement et non par ordre alphabétique (de sorte que “place 3” précède “lieu 20”, etc.). J’ai un DataGridView, où j’ai défini un DataView en tant que DataSource. Le DataView contient un DataTable créé avec certaines valeurs d’une firebase database. Les types de colonne sont ssortingng. J’ai un IComparer, qui fait ce qu’il devrait, mais je n’arrive pas à comprendre comment l’utiliser, car je ne parviens pas à savoir comment faire le sorting. L’événement DataGridView.SortCompare, qui serait parfait , ne fonctionne pas car il est databound. Le DataView.Sort n’accepte que les chaînes avec des noms de colonnes et des ordres de sorting.

Très ennuyant. J’ai essayé de lire les problèmes liés ici sur StackOverflow, et cherché beaucoup sur Google, mais je ne trouve pas grand chose à ce sujet. La seule chose que je trouve réellement consiste à utiliser la méthode Sort (chaîne) de l’affichage de données, qui ne fonctionnera pas, car elle est sortingée par ordre alphabétique.

Est-ce que quelqu’un sait comment faire cela sans trop de problèmes? Ça doit être d’autres que moi qui luttent avec ça? Je ne veux vraiment pas réimplémenter l’intégralité des classes datagridview ou dataview, juste pour obtenir un sorting personnalisé …

Mise à jour : au cas où quelqu’un se poserait la question, je cherche toujours une bonne réponse à ce problème. Bien qu’entre-temps, j’ai fini par créer ma propre classe de table simple, puis l’introduire manuellement dans une vue de données (datagridview). Redéfinition de la méthode SortCompare. Peu ennuyeux, mais ce n’était pas trop difficile, car je n’avais besoin que d’afficher des valeurs (aucune édition ou quoi que ce soit) et pouvais donc tout convertir en chaînes.

Jetez un coup d’œil à cette page MSDN et à ce billet de blog . En principe, vous devez configurer le sorting au niveau de la source de données (que ce soit un ObjectDataSource ou un SqlDataSource) et non du GridView.

Autant que je sache, la classe DataView ne prend en charge rien d’autre qu’un simple sorting croissant / décroissant. Sans voir le code où vous chargez et liez les données, il est difficile de faire une recommandation spécifique, mais vous pouvez soit:

  1. Chargez vos données dans une liste au lieu d’un DataTable, appelez la méthode Sort en transmettant votre méthode de comparaison, puis liez-vous à cette liste.
  2. Créez un code ObjectDataSource dans votre code aspx qui récupère les données directement à partir d’une classe et configurez ce dernier pour qu’il utilise votre IComparer.

Ce code devrait fonctionner. Il est similaire à ListViewItemSorter de ListView. Utiliser IComparer.

Utiliser:

private void dgv_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) { MyDataGridHelper.DataGridSort(dgv, e.ColumnIndex); } 

MyDataGridHelper.cs:

 public class MyDataGridHelper { public static void DataGridSort(DataGridView dgv, int column) { DataGridViewCustomSorter dgvSorter = null; if (dgv.Tag == null || !(dgv.Tag is IComparer)) { dgvSorter = new DataGridViewCustomSorter(dgv); dgv.Tag = dgvSorter; } else { dgvSorter = (DataGridViewCustomSorter)dgv.Tag; } dgvSorter.SortColumn = column; dgv.Sort(dgvSorter); } private class DataGridViewCustomSorter : IComparer { private int ColumnIndex; private SortOrder OrderOfSort; private DataGridView myDataGridView; private TypeCode mySortTypeCode; public DataGridViewCustomSorter(DataGridView dgv) { myDataGridView = dgv; mySortTypeCode = Type.GetTypeCode(Type.GetType("System.Ssortingng")); ColumnIndex = 0; OrderOfSort = SortOrder.None; } public int Compare(object x, object y) { int result; DataGridViewRow dgvX, dgvY; dgvX = (DataGridViewRow)x; dgvY = (DataGridViewRow)y; ssortingng sx = dgvX.Cells[ColumnIndex].Value.ToSsortingng(); ssortingng sy = dgvY.Cells[ColumnIndex].Value.ToSsortingng(); //null handling if (sx == Ssortingng.Empty && sy == Ssortingng.Empty) result = 0; else if (sx == Ssortingng.Empty && sy != Ssortingng.Empty) result = -1; else if (sx != Ssortingng.Empty && sy == Ssortingng.Empty) result = 1; else { switch (mySortTypeCode) { case TypeCode.Decimal: Decimal nx = Convert.ToDecimal(sx); Decimal ny = Convert.ToDecimal(sy); result = nx.CompareTo(ny); break; case TypeCode.DateTime: DateTime dx = Convert.ToDateTime(sx); DateTime dy = Convert.ToDateTime(sy); result = dx.CompareTo(dy); break; case TypeCode.Ssortingng: result = (new CaseInsensitiveComparer()).Compare(sx, sy); break; default: result = (new CaseInsensitiveComparer()).Compare(sx, sy); break; } } if (OrderOfSort == SortOrder.Descending) result = (-result); return result; } public int SortColumn { set { if (ColumnIndex == value) { OrderOfSort = (OrderOfSort == SortOrder.Descending ? SortOrder.Ascending : SortOrder.Descending); } ColumnIndex = value; try { mySortTypeCode = Type.GetTypeCode(Type.GetType((myDataGridView.Columns[ColumnIndex]).Tag.ToSsortingng())); } catch { mySortTypeCode = TypeCode.Ssortingng; } } get { return ColumnIndex; } } public SortOrder Order { set { OrderOfSort = value; } get { return OrderOfSort; } } } //end class DataGridViewCustomSorter } //end class MyDataGridHelper 

Vous pouvez créer 2 colonnes cachées. Atsortingbuez la partie texte à la 1ère colonne masquée et la partie numérotée à la 2e colonne masquée. Maintenant, sortingez en fonction de ces colonnes cachées (sorting alpha pour la 1ère colonne et sorting numérique pour la 2ème colonne).

De cette manière, vous pouvez conserver la colonne d’origine à des fins d’affichage et disposer des 2 colonnes masquées pour le sorting.

Voici une solution ” Tri personnalisé à l’aide de l’événement SortCompare ” et ” Tri personnalisé à l’aide de l’interface IComparer “:

http://msdn.microsoft.com/en-us/library/ms171608.aspx

Vous pouvez déplacer la logique de sorting dans votre requête de firebase database et lui faire renvoyer une colonne supplémentaire contenant le bon ordre de sorting.

Ensuite (le long de la réponse de @True C Sharp), vous pourriez avoir une colonne cachée contenant cette valeur et sortinger par celle-ci plutôt que par la colonne d’affichage.

Cela suppose que la logique permettant de déterminer l’ordre de sorting peut être effectuée en SQL. Cela peut ne pas fonctionner si l’algorithme permettant de déterminer l’ordre de sorting est complexe.