1
votes

Comment peindre la bordure de la ligne sélectionnée dans un WinForms DataGrid?

 entrez la description de l'image ici J'ai un contrôle personnalisé dérivé de l'ancien WinForms DataGrid .
Je veux dessiner une bordure autour de la ligne sélectionnée lorsqu'un utilisateur clique dessus: la bordure de la ligne, pas la bordure d'une cellule, ou changer la couleur d'arrière-plan de la ligne, etc.

 entrez la description de l'image ici

Comme la ligne de l'exemple graphique (une ligne rouge sur la 3ème ligne du DataGrid).
Je ne veux pas que ce soit comme la première ligne, avec un fond bleu.

 entrez la description de l'image ici

J'ai vu cette question: Comment dessiner une bordure autour d'une cellule DataGridView pendant sa modification?
Je ne peux pas l'implémenter car le DataGrid n'a pas d'événement CellPainting .
En essayant quelque chose de différent, j'ai une erreur sur .Selected:

if (e.ColumnIndex != -1 && 
    e.RowIndex != -1 && dataGridView1[e.ColumnIndex, e.RowIndex].Selected)


11 commentaires

Quelqu'un aide ..? Suggestion?


Eh bien, il a été suggéré d'utiliser l'événement CellPainting. As-tu essayé? (Pour créer un événement, vous allez dans la fenêtre des propriétés du DGV et dans le volet des événements, double-cliquez sur le nom de l'événement)


Exemple: private void dataGridView1_CellPainting (expéditeur de l'objet, DataGridViewCellPaintingEventArgs e) {int yourcolumnindex = 2; // utilisez votre propre condition! if (e.RowIndex! = yourcolumnindex) return; e.Paint (e.ClipBounds, DataGridViewPaintParts.All); Rectangle r = e.CellBounds; r.Height--; r.Width--; ...


if (e.ColumnIndex == -1) e.Graphics.DrawLine (Pens.Red, r.Left, r.Top, r.Left, r.Bottom); if (e.ColumnIndex == dataGridView1.ColumnCount - 1) e.Graphics.DrawLine (Pens.Red, r.Right, r.Top, r.Right, r.Bottom); e.Graphics.DrawLine (Pens.Red, r.Left, r.Top, r.Right, r.Top); e.Graphics.DrawLine (Stylos.Red, r.Left, r.Bottom, r.Right, r. Bottom); e.Handled = vrai; }


Je n'ai pas d'événement CellPainting, seulement similaire à ce que je vois est Paint ...


@TaW L'OP utilise l'ancien Datagrid


Ah, ce n'est pas une bonne idée et évidemment même après plus de 20 heures, une mauvaise balise et un mauvais texte.


N'appelez pas un DataGridView un GridView ou un DataGrid et vice versa !! C'est faux et déroutant car ce sont des contrôles différents. Appelez toujours les choses par leur bon nom! Oui, il faut quatre lettres de plus à taper, mais lorsque vous demandez de l’aide, le moment est pas d’être aussi paresseux ..! -


Je ne comprends pas ce que vous dites, qu'est-ce que l'élément sinon DataGridView, GridView ou DataGrid.Data est sur la table qu'est-ce que c'est que?


Vous devez nous le dire ! Sélectionnez-le et regardez dans la fenêtre des propriétés !! Je serai l'un des 3 ..


J'ajoute une capture d'écran des propriétés dans Question ask .... Comment puis-je faire ce que je veux si @Jimmi convient à l'ancienne grille de données?


3 Réponses :



3
votes

Cette grille ressemble à un contrôle personnalisé dérivé de l'ancien Contrôle DataGrid .

Étant donné que, d'après les commentaires, cela semble être le cas, il n'y a pas vraiment grand chose à utiliser.
Abonnez-vous aux événements Paint et Scroll en utilisant les gestionnaires d'événements présentés ici, cela permet de dessiner un rectangle le long des bordures de la ligne sélectionnée, en tenant compte du décalage de défilement et de la barre de défilement verticale width (les ScrollBars sont des contrôles enfants du DataGrid, pas nécessairement de la taille par défaut, généralement renvoyés par SystemInformation.VerticalScrollBarWidth).

Vous ne pourrez peut-être pas: p >

  • cast DotKasa.Kontrole.MyDataGrid directement dans DataGrid . Si vous ne pouvez pas, ajoutez le contrôle DataGrid à la boîte à outils de votre projet (ouvrez la boîte à outils, faites un clic droit à l'intérieur, sélectionnez Choisir des éléments ... , recherchez le DataGrid et cochez-le).
  • utilisez certaines des méthodes / propriétés natives affichées ici: le contrôle personnalisé peut avoir masqué ou remplacé certaines d'entre elles pour changer le comportement sans appeler base .

Ajoutez ce code à votre formulaire et voyez comment ça se passe:

int dataGridPenSize = 3;

private void MyDataGrid_Paint(object sender, PaintEventArgs e)
{
    var rect = GetDataGridCurrentRowRect(sender as DataGrid);
    if (rect != Rectangle.Empty) {
        using (var pen = new Pen(Color.Red, dataGridPenSize)) {
            e.Graphics.DrawRectangle(pen, rect);
        }
    }
}

private void MyDataGrid_Scroll(object sender, EventArgs e) 
    => (sender as Control).Invalidate();

private Rectangle GetDataGridCurrentRowRect(DataGrid dg)
{
    int scrollbarWidth = GetVerticalScrollBarWidth(dg);
    var bounds = dg.GetCurrentCellBounds();
    int upperLimit = dg.PreferredRowHeight + (dg.CaptionVisible ? dg.CaptionFont.Height + 4 : 0);
    if (bounds.Y <= upperLimit) return Rectangle.Empty;
    var rect = new Rectangle (
        new Point(dg.RowHeaderWidth, bounds.Y), 
        new Size(dg.PreferredSize.Width - dg.RowHeaderWidth - dataGridPenSize - scrollbarWidth, bounds.Height));
    return rect;
}

private int GetVerticalScrollBarWidth(DataGrid dg) {
    var vScroll = dg.Controls.OfType<VScrollBar>().FirstOrDefault();
    return vScroll == null ? 0 : vScroll.Width; 
}


13 commentaires

Its Works Brother, merci :) :):):), une autre question comment changer la largeur de la bordure du rectangle pour qu'elle soit plus massive?


Voir la modification. La barre de défilement verticale est également calculée. Vous pouvez utiliser int dataGridPenSize comme propriété publique, pour le modifier au moment de l'exécution, si nécessaire. La couleur du stylo peut également être une propriété publique.


cela ne va pas bien, son rectangle en gras mais lorsque vous changez la ligne sélectionnée, sur la dernière ligne avant le clic, reste le rectangle avec une bordure de 1 largeur, et c'est le cas pour tout autre derrière, cliquez sur la ligne suivante ... si je change 6 lignes différentes, cliquez sur, sur la dernière ligne est un rectangle ok en gras, mais sur 5 autres, un rectangle de 1 largeur


encore une question Jimi ... Savez-vous comment supprimer la couleur de sélection d'arrière-plan sur la ligne sur cet ancien DataGrid? Au début de ma demande, je place une capture d'écran où se trouve la ligne sélectionnée de couleur bleue, et je ne veux pas être cette couleur bleue, je veux être une couleur de fond transparente, être juste un rectangle sur la ligne sélectionnée?


Avez-vous remarqué que j'ai changé le code avant vos derniers commentaires? Si vous avez deux bordures différentes, vous n'avez pas implémenté ce code tel quel. + Ce code ne repeint pas la sélection colorée, il n'est pas affiché dans un DataGrid standard. Votre contrôle personnalisé peut le repeindre, mais je ne peux pas le tester, je n'ai pas ce contrôle. Essayez ce code avec un DataGrid standard et voyez si vous avez un comportement différent.


Oui, je remarque mais je pense que vous ne comprenez pas ce que j'essaie de vous dire ... vérifier poser une question j'ajoute une nouvelle image, avec un rectangle bleu, la ligne sélectionnée est peinte avec une largeur de 4, et avant la ligne sélectionnée, et avant avant la ligne sélectionnée est peint avec une largeur de 2,3 je suppose ... Et ce n'est pas la règle, parfois, mais quand je fais défiler vers le bas, cela fonctionne bien par moments, et sur des moments alors ne ...


Si vous avez des dessins résiduels (lignes qui persistent sur ce DataGrid), vous n'êtes probablement pas abonné à l'événement Scroll , en utilisant le gestionnaire d'événements MyDataGrid_Scroll , qui efface la ligne précédente. Ce code: private void MyDataGrid_Scroll (objet expéditeur, EventArgs e) => (expéditeur en tant que contrôle) .Invalidate (); . Vous devez utiliser ce gestionnaire, comme indiqué dans la réponse. Abonnez-vous une fois, bien sûr. Vérifiez si vous avez d'autres gestionnaires du même événement.


Je suis abonné avec ce code de ligne que je propose: this.dgRacuni.Scroll + = new System.EventHandler (this.dgRacuni_Scroll); C'est bon, je ne veux pas vous déranger, dites-moi simplement que vous pensez comment définir la couleur de la ligne d'arrière-plan de la sélection transparente pour qu'elle soit transparente dans l'ancienne grille de données? Sur l'image qui est de couleur bleu clair ... J'essaie les propriétés de dg SelectionBackColor, mais cela ne fonctionne pas, et le code creux ne réussit pas trop. Avez-vous une suggestion peut-être pour cela? Et encore une fois merci beaucoup pour le rectangle.


Vous ne me dérangez pas, j'essaie simplement de déterminer le problème pour que je puisse le résoudre. Il est possible que votre contrôle ne déclenche pas l'événement Scroll lorsque vous cliquez / sélectionnez des éléments. Pour le vérifier, abonnez-vous à MouseDown et ajoutez (sender as Control) .Invalidate (); au gestionnaire.


Maintenant, pour moi, le plus gros problème est de définir la couleur transparente pour la ligne d'arrière-plan de sélection.


Voir cette animation , c'est ainsi que je vois le DataGrid. L'arrière-plan de la sélection n'est pas peint. Si vous faites référence à la SelectionBackColor , définissez-la sur la même couleur que la propriété BackColor . Idem avec la propriété AlternatingBackColor . Essayez également d'Invalidate () dans l'événement CurrentCellChanged (au lieu de MouseDown , ce qui est utile pour tester la différence lorsqu'une sélection est faite).


Oui, c'est besoin de moi de l'animation comme ça exactement. Ce que je veux faire. J'essaie tout ce que vous me dites, j'ai mis this.dgRacuni.SelectionBackColor = dgRacuni.BackColor; this.dgRacuni.AlternatingBackColor = dgRacuni.BackColor; et j'appelle dgRacuni.Invalidate () dans la méthode CurrentCellChanged mais le résultat est le même, je ne sais pas quoi faire, quand faire, je n'ai pas vu le changement ...


Si vous ne voyez pas de changements, peut-être que ces méthodes ne sont pas appelées. Mettez des points d'arrêt dans les gestionnaires et voyez si le code y est interrompu. Sinon, essayez avec un nouveau projet, ajoutez juste ce DataGrid et testez-le. Peut-être publier le projet quelque part (y compris le contrôle personnalisé), afin que je puisse y jeter un coup d'œil.



1
votes

Pour avoir un contrôle total sur l'apparence des lignes et des colonnes, vous devez généralement créer des styles de colonnes personnalisés en utilisant l'un des styles de colonnes intégrés existants comme DataGridTextBoxColumn ou DataGridBoolColumn ou la base DataGridColumnStyle . Ensuite, vous pouvez personnaliser le comportement en remplaçant les propriétés et les méthodes de la classe.

Vous trouverez cet article très utile:

Exemple - Dessiner une bordure pour la ligne DataGrid

entrez la description de l'image ici

private void Form1_Load(object sender, EventArgs e)
{
    var dt = new DataTable();
    dt.Columns.Add("Id", typeof(int));
    dt.Columns.Add("Name", typeof(string));
    dt.Rows.Add(1, "A");
    dt.Rows.Add(2, "B");
    dt.Rows.Add(3, "C");

    var dg = new DataGrid();
    dg.Dock = DockStyle.Fill;
    var ts = new DataGridTableStyle();
    ts.GridColumnStyles.Add(new MyDataGridTextBoxColumn()
    { MappingName = "Id", HeaderText = "Id" });
    ts.GridColumnStyles.Add(new MyDataGridTextBoxColumn()
    { MappingName = "Name", HeaderText = "Name" });
    dg.TableStyles.Add(ts);

    this.Controls.Add(dg);
    dg.DataSource = dt;
}
public class MyDataGridTextBoxColumn : DataGridTextBoxColumn
{
    protected override void Paint(Graphics g, Rectangle bounds, CurrencyManager 
        source, int rowNum, Brush backBrush, Brush foreBrush, bool alignToRight)
    {
        base.Paint(g, bounds, source, rowNum, backBrush, foreBrush, alignToRight);
        if (this.DataGridTableStyle.DataGrid.CurrentRowIndex == rowNum)
        {
            g.DrawLine(Pens.Red, bounds.Left - 1, bounds.Top,
                bounds.Right + 1, bounds.Top);
            g.DrawLine(Pens.Red, bounds.Left - 1, bounds.Bottom -1 , 
                bounds.Right + 1, bounds.Bottom - 1);
        }
    }
}


2 commentaires

Merci pour la réponse, je résolve l'erreur avec la réponse @Jimi.


Bien d'entendre ça. Si la réponse de Jimi a résolu le problème, n'hésitez pas à la marquer comme acceptée :) - Je savais que c'était une question plutôt ancienne, mais je voulais garder cette option ici pour les futurs lecteurs car c'est généralement la voie à suivre en ce qui concerne personnalisation de l'apparence de l'ancien DataGrid.