FAQ C#Consultez toutes les FAQ

Nombre d'auteurs : 39, nombre de questions : 272, dernière mise à jour : 24 mai 2015  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


SommaireWinFormsContrôles de liste (13)
précédent sommaire suivant
 

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);

Mis à jour le 2 novembre 2004 Swoög

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); 
    } 
}

Mis à jour le 10 avril 2006 neguib

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";
Le titre dans la colonne sera bien celui assigné, et on n'a pas touché à la structure interne de la table.

Mis à jour le 10 avril 2006 crjo

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);
Astuce : en gardant une référence sur le style de colonne supprimée (hiddenColStyle), on peut par la suite décider de réafficher la colonne. Cette technique est utile si on veut choisir dynamiquement les colonnes à afficher.

Code c# : Sélectionner tout
tableStyle.GridColumnStyles.Add(hiddenColStyle);

Mis à jour le 10 avril 2006 crjo

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); } 
  
}

Mis à jour le 22 août 2006 neguib

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); 
        } 
    } 
  
}

Mis à jour le 22 août 2006 neguib

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); } 
    } 
  
}
Utilisable par exemple ainsi :

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(); } 
}

Mis à jour le 22 août 2006 neguib

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); 
    } 
}
Utilisable, par exemple, de la façon suivante :

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(); 
}

Mis à jour le 22 août 2006 neguib

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); 
    } 
}
Utilisable par exemple ainsi sur une modification DataGrid.DataSource :

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(); 
}
Cet exemple peut bien évidemment être amélioré, si l'on souhaite également répercuter de façon dynamique des ajouts ou suppressions de lignes.

Mis à jour le 22 août 2006 neguib

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); 
}

Mis à jour le 10 avril 2006 neguib

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); 
}

Mis à jour le 2 janvier 2007 Jérôme Lambert

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;

Mis à jour le 10 avril 2006 neguib

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); } 
    } 
}
Ensuite, il suffit d'intercepter le clic sur les colonnes (évènement ColumnClick) et d'instancier cette classe.

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); 
}
Remarque : j'effectue ici une comparaison de chaines, il faudra implémenter différemment si on compare des nombres par exemple.

Mis à jour le 22 août 2006 nico-pyright(c)

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 ça


Réponse à la question

Liens sous la question
précédent sommaire suivant
 

Les 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 © 2017 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.

 
Responsable bénévole de la rubrique Microsoft DotNET : Hinault Romaric -