web-dev-qa-db-fra.com

TreeNode sélectionné BackColor alors que TreeView n'est pas centré

Existe-t-il un moyen simple de faire en sorte qu'un TreeNode sélectionné conserve ses SystemColors.Highlight BackColor alors que TreeView n'a pas le focus? Parce que même avec HideSelection défini sur false, le BackColor sélectionné est presque impossible à voir. 

TreeNode sélectionné lorsque TreeView a le focus:

Focused

TreeNode sélectionné alors que TreeView n'a pas le focus:

Unfocused

Merci d'avance.

EDIT: Je suis conscient que je pourrais définir DrawMode sur OwnerDrawAll, puis ajouter un événement DrawNode personnalisé. J'ai déjà essayé de le faire auparavant, le problème est que je ne sais pas comment dessiner correctement l'image correspondante de la TreeNode.

21
Spark

La solution fonctionne comme un charme:

public TreeNode previousSelectedNode = null;
private void treeView1_Validating(object sender, System.ComponentModel.CancelEventArgs e)
{
    treeView1.SelectedNode.BackColor = SystemColors.Highlight;
    treeView1.SelectedNode.ForeColor = Color.White;
    previousSelectedNode = treeView1.SelectedNode;
}

private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
    if(previousSelectedNode != null)
    {
        previousSelectedNode.BackColor = treeView1.BackColor;
        previousSelectedNode.ForeColor = treeView1.ForeColor;
    }
}
13
Spark

Si vous souhaitez conserver la couleur d'arrière-plan SystemColors.Highlight, c'est que vous n'avez pas besoin de définir la propriété TreeView de DrawMode sur TreeViewDrawMode.OwnerDrawAll. Le paramétrer sur TreeViewDrawMode.OwnerDrawText devrait suffire, vous n'avez donc pas à vous soucier de dessiner la TreeNode correspondante ImageKey.

  1. Définissez le TreeView.DrawMode sur TreeViewDrawMode.OwnerDrawText:

    treeView.DrawMode = TreeViewDrawMode.OwnerDrawText;
    
  2. Définissez le Treview.HideSelection sur false afin que les états de nœud soient conservés tels que sélectionnés:

    treeView.HideSelection= false;
    
  3. Ajoutez le gestionnaire d'événements DrawNode pour dessiner l'arrière-plan à l'aide de SystemColors.Highlight color:

    private void treeView_DrawNode(object sender, DrawTreeNodeEventArgs e)
    {
      if (e.Node == null) return;
    
      // if treeview's HideSelection property is "True", 
      // this will always returns "False" on unfocused treeview
      var selected = (e.State & TreeNodeStates.Selected) == TreeNodeStates.Selected;
      var unfocused = !e.Node.TreeView.Focused;
    
      // we need to do owner drawing only on a selected node
      // and when the treeview is unfocused, else let the OS do it for us
      if (selected && unfocused)
      {
        var font = e.Node.NodeFont ?? e.Node.TreeView.Font;
        e.Graphics.FillRectangle(SystemBrushes.Highlight, e.Bounds);
        TextRenderer.DrawText(e.Graphics, e.Node.Text, font, e.Bounds, SystemColors.HighlightText, TextFormatFlags.GlyphOverhangPadding);
      }
      else
      {
        e.DrawDefault = true;
      }
    }
    
12
IronGeek

J'utilise cette solution et ça marche mieux

private void treeView1_Enter(object sender, EventArgs e)
{
   if (treeView1.SelectedNode != null)
   {
       treeView1.SelectedNode.BackColor = Color.Empty;
       treeView1.SelectedNode.ForeColor = Color.Empty;
   }
}

private void treeView1_Leave(object sender, EventArgs e)
{
   if (treeView1.SelectedNode != null)
   {
       treeView1.SelectedNode.BackColor = SystemColors.Highlight;
       treeView1.SelectedNode.ForeColor = Color.White;
   }
}

MODIFIER

Basé sur this documentation, 

La valeur par défaut est Color.Empty

Donc, dans treeView1_Enter il est préférable de définir la couleur comme ceci

treeView1.SelectedNode.BackColor = Color.Empty;
treeView1.SelectedNode.ForeColor = Color.Empty;

Réponse précédente

treeView1.SelectedNode.BackColor = treeView1.BackColor;
treeView1.SelectedNode.ForeColor = treeView1.ForeColor;
4
Afrig Aminuddin

si vous avez juste besoin de mettre en évidence le nœud sélectionné lorsque l'arborescence n'est plus au point, utilisez simplement treeView.HideSelection = false;

En réalité, par défaut, le nœud sélectionné est mis en surbrillance mais n'est pas visible. Il suffit donc de définir la propriété HideSelection sur false.

2
Vikash Kumar

Trouvé cette excellente solution ici (MSDN)

Ca a très bien fonctionné pour moi, j'espère que ça va aider quelqu'un d'autre.

  1. Ajoutez une nouvelle classe (fichier appelé MyTreeView.cs) à votre projet et collez le code ci-dessous.
  2. Compiler. 
  3. Déposez le nouveau contrôle appelé "MyTreeView" du haut de la boîte à outils sur votre formulaire.

Vous pouvez aussi le personnaliser si vous savez ce que vous faites.

using System;
using System.Drawing;
using System.Windows.Forms;



class MyTreeView : TreeView {
    public MyTreeView() {
        this.DrawMode = TreeViewDrawMode.OwnerDrawText;
    }
    protected override void OnDrawNode(DrawTreeNodeEventArgs e) {
        TreeNodeStates state = e.State;
        Font font = e.Node.NodeFont ?? e.Node.TreeView.Font;
        Color fore = e.Node.ForeColor;
        if (fore == Color.Empty) fore = e.Node.TreeView.ForeColor;
        if (e.Node == e.Node.TreeView.SelectedNode) {
            fore = SystemColors.HighlightText;
            e.Graphics.FillRectangle(SystemBrushes.Highlight, e.Bounds);
            ControlPaint.DrawFocusRectangle(e.Graphics, e.Bounds, fore, SystemColors.Highlight);
            TextRenderer.DrawText(e.Graphics, e.Node.Text, font, e.Bounds, fore, TextFormatFlags.GlyphOverhangPadding);
        }
        else {
            e.Graphics.FillRectangle(SystemBrushes.Window, e.Bounds);
            TextRenderer.DrawText(e.Graphics, e.Node.Text, font, e.Bounds, fore, TextFormatFlags.GlyphOverhangPadding);
        }
    }
}
1
ukie

Cette variante de IronGeeks answer fonctionne pour moi et fonctionne avec Bold Nodes :

Private Sub TreeView1_DrawNode(sender As Object, e As DrawTreeNodeEventArgs) Handles trvIdent.DrawNode
    Dim treeView = e.Node.TreeView
    Dim selected = (e.Node Is treeView.SelectedNode)
    Dim unfocused = Not treeView.Focused
    Dim font = If(e.Node.NodeFont IsNot Nothing, e.Node.NodeFont, treeView.Font)
    Dim textSize = e.Graphics.MeasureString(e.Node.Text, font)
    Dim bounds = New Rectangle(e.Bounds.X, e.Bounds.Y,
                               Convert.ToInt32(textSize.Width),
                               Math.Max(Convert.ToInt32(textSize.Height), e.Bounds.Height))

    e.DrawDefault = False

    If selected Then
        e.Graphics.FillRectangle(SystemBrushes.Highlight, bounds)
        e.Graphics.DrawString(e.Node.Text, font, SystemBrushes.HighlightText, bounds.Location)
    Else
        e.Graphics.FillRectangle(SystemBrushes.Window, bounds)
        e.Graphics.DrawString(e.Node.Text, font, SystemBrushes.WindowText, bounds.Location)
    End If
    'e.Graphics.DrawRectangle(Pens.Magenta, bounds)
End Sub

La principale différence est que le dessin personnalisé est effectué même si la variable TreeView est activée. Et DrawString() est utilisé à la place de DrawText().

0
dummy

c'est le comportement par défaut pour l'arborescence. Tout ce que vous devez faire pour le changer est d’autoriser le drawode. Il y a une autre réponse de débordement de pile qui l'explique mieux que je ne pourrais le faire ici.

Comment changer la couleur d'arrière-plan du noeud sélectionné dans TreeView à l'aide de TreeViewDrawMode.OwnerDrawAll?

0
Allen

Le code suivant fonctionne même avec des nœuds sélectionnés par programme.

public TreeNode m_previousSelectedNode = null;
private void m_treeView_AfterSelect(object sender, TreeViewEventArgs e)
{
    if (m_previousSelectedNode != null)
    {
        m_previousSelectedNode.BackColor = m_treeView.BackColor;
        m_previousSelectedNode.ForeColor = m_treeView.ForeColor;
    }

    e.Node.BackColor = SystemColors.Highlight;
    e.Node.ForeColor = Color.White;

    m_previousSelectedNode = m_treeView.SelectedNode;
}
0
Elephant