29

有没有一种简单的方法可以让选定的 TreeNode 在 TreeView 没有焦点时保留其 SystemColors.Highlight BackColor?因为即使 HideSelection 设置为 false,所选的 BackColor 也几乎是看不到的。

TreeView 具有焦点时选定的 TreeNode:

专注

TreeView 没有焦点时选择的 TreeNode:

不专心

提前致谢。

编辑:我知道我可以将 DrawMode 设置为 OwnerDrawAll,然后添加一个自定义 DrawNode 事件。我之前确实尝试过,我遇到的问题是我不知道如何正确绘制 TreeNode 的相应 ImageKey。

4

8 回答 8

18

如果您只想要保留SystemColors.Highlight背景颜色,则无需将TreeView'DrawMode属性设置为TreeViewDrawMode.OwnerDrawAll. 将其设置为TreeViewDrawMode.OwnerDrawText就足够了,因此您无需担心绘制TreeNode' 对应的ImageKey.

  1. 设置TreeView.DrawModeTreeViewDrawMode.OwnerDrawText

    treeView.DrawMode = TreeViewDrawMode.OwnerDrawText;
    
  2. 将 设置Treview.HideSelectionfalse,以便节点状态将保持为选中状态:

    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;
      }
    }
    
于 2014-01-18T04:05:42.870 回答
14

解决方案就像一个魅力:

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;
    }
}
于 2014-01-18T04:17:50.947 回答
8

我使用这个解决方案,效果更好

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;
于 2017-01-03T04:05:45.837 回答
2

如果您只需要在树视图失焦时突出显示选定的节点,那么只需使用 treeView.HideSelection = false;

实际上,默认情况下,选定的节点是突出显示的,但不可见,所以我们只需要将 HideSelection 属性设置为 false。

于 2016-08-25T07:32:30.440 回答
1

在这里找到了这个很棒的解决方案(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);
        }
    }
}
于 2016-10-29T04:52:57.037 回答
0

这是树视图的默认行为。更改它所需要做的就是覆盖drawnode。还有另一个堆栈溢出答案比我在这里解释得更好。

如何使用 TreeViewDrawMode.OwnerDrawAll 更改 TreeView 中选定节点的背景颜色?

于 2014-01-18T01:46:09.750 回答
0

以下代码甚至适用于以编程方式选择的节点。

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;
}
于 2015-11-12T15:11:38.430 回答
0

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().

于 2017-07-14T09:47:03.230 回答