FAQ C#Consultez toutes les FAQ
Nombre d'auteurs : 41, nombre de questions : 274, dernière mise à jour : 27 mai 2018 Ajouter une question
Cette FAQ a été réalisée pour répondre aux questions les plus fréquemment posées concernant C# sur le forum Développement DotNET
Je tiens à souligner qu'elle ne garantit en aucun cas que les informations qu'elle contient sont correctes ; les auteurs font le maximum, mais l'erreur est humaine. Si vous trouvez une erreur, ou que vous souhaitez devenir rédacteur, lisez ceci .
Sur ce, je vous souhaite une bonne lecture.
Commentez cette FAQ : Commentez
- Comment sélectionner via le code une ligne d'un DataGrid ?
- Comment sélectionner toute la ligne lors d'un click dans une cellule ?
- Comment renommer une colonne de DataGrid ?
- Comment masquer une colonne de DataGrid ?
- Comment modifier la hauteur des lignes du DataGrid ?
- Comment dimensionner automatiquement la hauteur des lignes du DataGrid ?
- Comment implémenter l'évènement CurrentRowChanged du DataGrid ?
- Comment identifier la partie cliquée du DataGrid ?
- Comment obtenir le nombre de lignes du DataGrid par son BindingContext ?
- Comment capturer un clic dans l'icône d'un TreeNode ?
- Comment déterminer le TreeNode survolé par la souris ?
- Comment colorier une cellule en mode Details ?
- Comment trier les colonnes d'une listview en cliquant sur leurs intitulés ?
Il suffit simplement d'utiliser une méthode native des DataGrid :
(On suppose que MyDG est un DataGrid fonctionnel et Num_Row un entier contenant l'index de la colonne)
Code c# : | Sélectionner tout |
MyDG.Select(Num_Row);
La Classe System.Windows.Forms.DataGrid.HitTestInfo vous permet de déterminer la partie d'un contrôle DataGrid sur laquelle l'utilisateur a cliqué. Pour ce faire, vous avez besoin d'utiliser la méthode HitTest du DataGrid que nous nommons ici pour l'exemple 'DG' :
Code c# : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | using System; using System.Drawing; using System.Windows.Forms; //... private void DG_MouseUp(object sender, MouseEventArgs e) { //recupérer les coordonnées de la souris Point p = new Point(e.X, e.Y); //déterminer la partie cliquée du datagrid DataGrid.HitTestInfo HTI = DG.HitTest(p); //si c'est un type 'cellule' if (HTI.Type == DataGrid.HitTestType.Cell) { //définir la cellule en cours DG.CurrentCell = new DataGridCell(HTI.Row, HTI.Column); //selectionner la ligne correspondante DG.Select(HTI.Row); } } |
On suppose que le DataGrid est associé à une DataTable. Il faut effectuer les actions suivantes :
- créer un DataGridTableStyle pour la table en question ;
- ajouter le style au DataGrid ;
- renommer la propriété HeaderText du style de colonne (DataGridColumnStyle) correspondant.
Code c# : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // table est une DataTable dataGrid1.DataSource = table; // on crée une table de style qui permettra de renommer les colonnes. DataGridTableStyle tableStyle = new DataGridTableStyle(); // IMPORTANT: il faut associer le nom de la table au style tableStyle.MappingName = table.TableName; // en ajoutant le style au DataGrid, les DataGridColumnStyle sont automatiquement créés // en fonction de la table spécifiée par tableStyle.MappingName dataGrid1.TableStyles.Add(tableStyle); // on suppose que la table contient une colonne nommée "col_name" tableStyle.GridColumnStyles["col_name"].HeaderText = "colonne renommée pour datagrid"; |
On suppose que le DataGrid est associé à une DataTable. Il faut effectuer les actions suivantes :
- créer un DataGridTableStyle pour la table en question ;
- ajouter le style au DataGrid ;
- personnaliser le style pour retirer le style de colonne (DataGridColumnStyle) correspondant.
Code c# : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | // table est de type : DataTable dataGrid1.DataSource = table; // on crée une table de style qui permettra de masquer une ou plusieurs colonnes. DataGridTableStyle tableStyle = new DataGridTableStyle(); // IMPORTANT: il faut associer le nom de la table au style tableStyle.MappingName = table.TableName; // en ajoutant le style au DataGrid, celui-ci va automatiquement utiliser le style // pour afficher la table associé (c'est pour ça qu'il est important // d'assigner MappingName) dataGrid1.TableStyles.Add(tableStyle); // on suppose que la table contient une colonne nommée "hidden" // on définit une référence sur la colonne que l'on veut cacher DataGridColumnStyle hiddenColStyle = tableStyle.GridColumnStyles["hidden"]; // en enlevant la colonne des styles de colonne, la colonne n'apparaîtra // plus dans le DataGrid. tableStyle.GridColumnStyles.Remove(hiddenColStyle); |
Code c# : | Sélectionner tout |
tableStyle.GridColumnStyles.Add(hiddenColStyle);
Ici, le souci à résoudre est que l'accesseur DataGrid.DataGridRows est déclaré internal. Cette propriété expose le tableau des objets DataGridRow, elle même classe internal de System.Windows.Forms. Pour atteindre sa propriété Height, il y a tout de même une solution qui passe par les fonctionnalités de System.Windows.Reflection. Pour la démonstration, nous implémentons notre propre classe MonDataGrid dérivée de DataGrid :
Code c# : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | using System; using System.Reflection; using System.Windows.Forms; public class MonDataGrid : DataGrid { public MonDataGrid() : base() { } //... //méthode publique qui permet la modification // de la hauteur de la ligne indiquée public void setRowHeight(int rowindex, int rowheight) { //Recupérer le tableau des lignes Object[] rows = GetRows(); //Ici par convention on décide de modifier // toutes les lignes pour une valeur négative if (rowindex < 0) { foreach (object row in rows) { setHeight(row, rowheight); } } else { setHeight(rows[rowindex], rowheight); } } //obtient toutes les lignes par reflection private object[] GetRows() { BindingFlags bf = BindingFlags.Instance | BindingFlags.NonPublic; Type t = this.GetType().BaseType; MethodInfo mi = t.GetMethod("get_DataGridRows", bf); return ((Object[])(mi.Invoke(this, null))); } //modifie la hauteur de ligne par reflection private void setHeight(object row, int rowheight) { row.GetType().GetProperty("Height").SetValue(row, rowheight, null); } } |
Dans un premier temps, il faut d'abord savoir Comment modifier la hauteur des lignes du DataGrid ? .
Nous utiliserons cette classe MonDataGrid dérivée de DataGrid et notamment sa méthode publique setRowHeight.
Code c# : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | using System; using System.Drawing; using System.Reflection; using System.Windows.Forms; public class MonDataGrid : DataGrid { //... //méthode publique qui dimensionne automatiquement la hauteur des lignes public void AutoSizeRows() { using (Graphics g = Graphics.FromHwnd(this.Handle)) { SizeF s = g.MeasureString("test", this.Font); int h = Convert.ToInt32(s.Height); h += 8; setRowHeight(-1, h); } } } |
La classe DataGrid ne possède nativement que l'évènement CurrentCellChanged pour signaler le changement de cellule. Il nous faut donc simplement, lors de cet évènement, comparer la ligne à laquelle correspond la cellule avec un champ privé représentant la ligne précedemment sélectionnée. Ainsi nous pouvons déclencher un nouvel évènement que nous appelons CurrentRowChanged à partir de la surcharge de la méthode DataGrid.OnCurrentCellChanged. Nous implémenterons une classe MonDataGrid dérivée de DataGrid capable de déclencher un évènement CurrentRowChanged pour signaler la ligne ayant actuellement le focus et, par là même, distinguer celle correspondant à l'ajout d'un enregistrement.
Code c# : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | using System; using System.Drawing; using System.Reflection; using System.Windows.Forms; public class MonDataGrid : DataGrid { public event EventHandler CurrentRowChanged; public MonDataGrid() : base() { this.currentRowIndex = -1; } //... //accesseur publique qui obtient l'index de la ligne courante public int CurrentRow { get { return this.currentRowIndex; } } private int currentRowIndex; //surcharge de la méthode base.OnCurrentCellChanged protected override void OnCurrentCellChanged(EventArgs e) { base.OnCurrentCellChanged(e); if (this.CurrentCell.RowNumber != this.currentRowIndex) { this.currentRowIndex = this.CurrentCell.RowNumber; this.OnCurrentRowChanged(e); } } //déclenche l'évènement CurrentRowChanged protected virtual void OnCurrentRowChanged(EventArgs e) { if (this.CurrentRowChanged != null) { this.CurrentRowChanged(this, e); } } } |
Code c# : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 | private void DataGrid1CurrentRowChanged(object sender, System.EventArgs e) { MonDataGrid dg = (MonDataGrid)sender; int rowindex = dg.CurrentRow; if (rowindex == ((DataTable)dg.DataSource).Rows.Count) { this.LComment.Text = "Vous êtes sur la ligne d'ajout d'enregistrement"; } else { this.LComment.Text = "ligne " + rowindex.ToString(); } } |
La Classe DataGrid.HitTestInfo vous permet de déterminer la partie d'un contrôle DataGrid sur laquelle l'utilisateur a cliqué. Pour ce faire, il nous faut :
- Déterminer les coordonnées du clic par la méthode HitTest ;
- Utiliser la propriété HitTestInfo.Type, qui renvoie une valeur de l'énumération DataGrid.HitTestType.
Nous implémenterons une classe MonDataGrid dérivée de DataGrid capable d'exposer par un accesseur sa partie cliquée.
Code c# : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public class MonDataGrid : DataGrid { //... //accesseur publique qui obtient la partie cliquée public DataGrid.HitTestType ClickType { get { return this.currentClickType; } } private DataGrid.HitTestType currentClickType; //surcharge de base.OnMouseDown protected override void OnMouseDown(MouseEventArgs e) { this.currentClickType = this.HitTest(e.X, e.Y).Type; base.OnMouseDown(e); } } |
Code c# : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 | using System.Text; //... private void DataGrid1MouseDown(object sender, System.Windows.Forms.MouseEventArgs e) { MonDataGrid dg = (MonDataGrid)sender; StringBuilder sb = new StringBuilder("La partie cliquée est de type: "); sb.Append(dg.ClickType.ToString()); dg.CaptionText = sb.ToString(); } |
La propriété DataGrid.BindingContext permet d'accéder à l'indexeur de l'objet BindingManagerBase sous-jascent. Et par là même, permet d'atteindre sa propriété BindingManagerBase.Count. Pour la démonstration, nous implémentons notre propre classe MonDataGrid dérivée de DataGrid.
Code c# : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public class MonDataGrid : DataGrid { //... //accesseur publique qui obtient le nombre de lignes public int DataRowsCount { get { return this.currentDataRowsCount; } } private int currentDataRowsCount; //surcharge de la méthode base.OnDataSourceChanged protected override void OnDataSourceChanged(System.EventArgs e) { if (this.DataSource != null) { this.currentDataRowsCount = this.BindingContext[this.DataSource, this.DataMember].Count; } else { this.currentDataRowsCount = 0; } base.OnDataSourceChanged(e); } } |
Code c# : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 | using System.Text; //... private void DataGrid1DataSourceChanged(object sender, EventArgs e) { StringBuilder sb = new StringBuilder("Le nombre de lignes est de: "); sb.Append(((MonDataGrid)sender).DataRowsCount.ToString()); this.LComment.Text = sb.ToString(); } |
Utilisons un TreeView appelé ici TreeView1 possédant nécessairement dans ce cas de figure une ImageList pour sa collection de TreeNode.
La capture de l'évènement Click se fait ici par la méthode TreeView.MouseDown afin de récupérer les coordonnées du pointeur de la souris.
La méthode ci-dessous GetNodeIconeRectangle permet de calculer le Rectangle de l'icône du TreeNode sélectionné. Il ne reste plus alors qu'à vérifier si le Point localisé du pointeur de la souris appartient à l'icône du TreeNode sélectionné.
Code c# : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | using System; using System.Drawing; using System.Windows.Forms; private void TreeView1_MouseDown(object sender, MouseEventArgs e) { Point p = new Point(e.X, e.Y); TreeNode selectedTreeNode = this.TreeView1.GetNodeAt(p); Rectangle imgRectangle; if (selectedTreeNode != null) { imgRectangle = GetNodeIconeRectangle(selectedTreeNode); if (imgRectangle.Contains(p)) { //traitement } } } private Rectangle GetNodeIconeRectangle(TreeNode node) { Size s = node.TreeView.ImageList.ImageSize; int h = node.TreeView.ItemHeight; int x = node.Bounds.X - s.Width; int y = node.Bounds.Y + ((h - s.Height) / 2); return new Rectangle(new Point(x, y), s); } |
Il faut pour cela traiter l'évènement MouseMove du TreeView :
Code c# : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 | /// <summary> /// Evènement MouseMove du treeView1 /// </summary> private void treeView1_MouseMove(object sender, MouseEventArgs e) { // Récupération du TreeNode survolé TreeNode currentNode = treeView1.GetNodeAt(e.X, e.Y); // Vérification que la souris survole bien un TreeNode if (currentNode != null) Console.WriteLine("Le node survolé est {0}", currentNode.Name); } |
L'objet ListViewSubItem a une propriété BackColor mais pour que l'assignation soit effective il ne faut pas oublier de modifier la propriété UseItemStyleForSubItems du ou des ListViewItem concerné(s) en lui attribuant la valeur false.
Si vous souhaitez effectuer cette opération par programmation, voici un exemple :
- Coloration en jaune de toute la première colonne d'un ListView1 :
Code c# : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 | using System; using System.Drawing; using System.Windows.Forms; //... foreach (ListViewItem lvi in this.ListView1.Items) { lvi.UseItemStyleForSubItems = false; lvi.SubItems[0].BackColor = Color.Yellow; } this.ListView1.View = View.Details; |
L'objet ListView dispose d'une propriété ListViewItemSorter de type IComparer. Cela permet d'implémenter sa propre gestion du tri.
Pour ce faire, il faut créer une classe dérivant de IComparer implémentant la méthode Compare.
Code c# : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | class ListViewItemComparer : IComparer { private int col; private SortOrder sortOrder; public ListViewItemComparer() { col = 0; sortOrder = Windows.Forms.SortOrder.Ascending; } public ListViewItemComparer(int column) { col = column; sortOrder = Windows.Forms.SortOrder.Ascending; } public ListViewItemComparer(int column, SortOrder s) { col = column; sortOrder = s; } public int Compare(object x, object y) { if (sortOrder == Windows.Forms.SortOrder.Ascending) { return string.Compare(((ListViewItem)(x)).SubItems(col).Text, ((ListViewItem)(y)).SubItems(col).Text); } else { return string.Compare(((ListViewItem)(y)).SubItems(col).Text, ((ListViewItem)(x)).SubItems(col).Text); } } } |
Code c# : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 | private void ListView1_ColumnClick(object sender, System.Windows.Forms.ColumnClickEventArgs e) { if (this.ListView1.Sorting == SortOrder.Ascending) { this.ListView1.Sorting = SortOrder.Descending; } else { this.ListView1.Sorting = SortOrder.Ascending; } this.ListView1.ListViewItemSorter = new ListViewItemComparer(e.Column, this.ListView1.Sorting); } |
Proposer une nouvelle réponse sur la FAQ
Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour çaLes sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2024 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.