TreeNode Выбранный BackColor, в то время как TreeView не сфокусирован

Есть ли простой способ, чтобы выбранный TreeNode сохранил свой SystemColors.Highlight BackColor, пока TreeView не имеет фокуса? Поскольку даже если для HideSelection установлено значение false, выбранный BackColor практически невозможно увидеть.

Выбранный TreeNode, в то время как TreeView имеет фокус:

ориентированные

Выбранный TreeNode, в то время как TreeView не имеет фокуса:

несфокусированный

Заранее спасибо.

РЕДАКТИРОВАТЬ: я знаю, что я мог бы установить DrawMode на OwnerDrawAll, а затем добавить пользовательское событие DrawNode. Я пытался сделать это ранее, проблема у меня в том, что я не знаю, как правильно нарисовать соответствующий ImageKey TreeNode.

8 ответов

Решение

Решение, работает как шарм:

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

Если сохранить SystemColors.Highlight цвет фона - это все, что вам нужно, тогда вам не нужно устанавливать TreeView"s DrawMode собственность на TreeViewDrawMode.OwnerDrawAll, Установка его в TreeViewDrawMode.OwnerDrawText должно быть достаточно, поэтому вам не нужно беспокоиться о рисовании TreeNodeсоответствует ImageKey,

  1. Установить TreeView.DrawMode в TreeViewDrawMode.OwnerDrawText:

    treeView.DrawMode = TreeViewDrawMode.OwnerDrawText;
    
  2. Установить Treview.HideSelection в false, так что состояния узла будут сохранены как выбранные:

    treeView.HideSelection= false;
    
  3. добавлять DrawNode обработчик событий для рисования фона с помощью SystemColors.Highlight цвет:

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

Я использую это решение, и оно работает лучше

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

РЕДАКТИРОВАТЬ

Основываясь на этой документации,

По умолчанию это Color.Empty

Итак, в treeView1_Enter лучше установить цвет так

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

Предыдущий ответ

treeView1.SelectedNode.BackColor = treeView1.BackColor;
treeView1.SelectedNode.ForeColor = treeView1.ForeColor;

Если вам просто нужно выделить выбранный узел, когда вид дерева выходит из фокуса, просто используйте treeView.HideSelection = false;

На самом деле по умолчанию выбранный узел подсвечивается, но не отображается, поэтому нам просто нужно присвоить свойству HideSelection значение false.

Нашел это отличное решение здесь (MSDN)

Работал отлично для меня, надеюсь, это поможет кому-то еще.

  1. Добавьте новый класс (файл с именем MyTreeView.cs) в ваш проект и вставьте код, показанный ниже.
  2. Компиляция.
  3. Удалите новый элемент управления "MyTreeView" из верхней части панели инструментов на форму.

Вы также можете настроить его, если знаете, что делаете

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

Это поведение по умолчанию для дерева. Все, что вам нужно сделать, чтобы изменить его, это переопределить drawnode. Есть еще один ответ о переполнении стека, который объясняет это лучше, чем я мог бы здесь.

Как изменить цвет фона выбранного узла в TreeView, используя TreeViewDrawMode.OwnerDrawAll?

Следующий код работает даже с программно выбранными узлами.

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

Этот вариант ответа IronGeeks работает для меня и работает с 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

Основное отличие состоит в том, что пользовательский рисунок выполняется, даже если TreeView сосредоточен. А также DrawString() используется вместо DrawText(),

Другие вопросы по тегам