TreeNode Selected BackColor, в то время как TreeView не сфокусирован
Есть ли простой способ, чтобы выбранный TreeNode сохранил свой SystemColors.Highlight BackColor, в то время как TreeView не имеет фокуса? Поскольку даже если HideSelection установлен в false, выбранный BackColor почти невозможно увидеть.
Выбранный TreeNode, в то время как TreeView имеет фокус:
![Focused]()
Выбранный TreeNode, в то время как TreeView не имеет фокуса:
![Unfocused]()
Спасибо заранее.
EDIT: Я знаю, что могу установить DrawMode на OwnerDrawAll, а затем добавить пользовательское событие DrawNode. Я делал это раньше, проблема заключается в том, что я не знаю, как правильно рисовать соответствующий TreeNode ImageKey.
Ответы
Ответ 1
Решение, работает как шарм:
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;
}
}
Ответ 2
Если сохранить фоновый цвет SystemColors.Highlight
- это все, что вам нужно, тогда вам не нужно устанавливать свойство TreeView
DrawMode
на TreeViewDrawMode.OwnerDrawAll
. Установка его на TreeViewDrawMode.OwnerDrawText
должна быть достаточной, поэтому вам не нужно беспокоиться о рисунке TreeNode
, соответствующем ImageKey
.
-
Установите TreeView.DrawMode
на TreeViewDrawMode.OwnerDrawText
:
treeView.DrawMode = TreeViewDrawMode.OwnerDrawText;
-
Установите Treview.HideSelection
на false
, так что состояния node будут сохранены как выбрано:
treeView.HideSelection= false;
-
Добавьте DrawNode
обработчик событий, чтобы нарисовать фон, используя цвет SystemColors.Highlight
:
private void treeView_DrawNode(object sender, DrawTreeNodeEventArgs e)
{
if (e.Node == null) return;
// if treeview 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;
}
}
Ответ 3
если вам просто нужно выделить выбранный node, когда древовидная структура выходит из фокуса, тогда просто используйте
treeView.HideSelection = false;
Фактически по умолчанию выбранный node подсвечивается, но не отображается, поэтому нам просто нужно сделать свойство HideSelection равным false.
Ответ 4
Я использую это решение, и оно работает лучше
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;
Ответ 5
это поведение по умолчанию для дерева. Все, что вам нужно сделать, чтобы изменить, это переопределить drawode. Существует еще один ответ, который объясняет это лучше, чем я мог здесь.
Как изменить цвет фона выбранного node в TreeView с помощью TreeViewDrawMode.OwnerDrawAll?
Ответ 6
Следующий код работает даже с программно выбранными узлами.
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;
}
Ответ 7
Нашел это отличное решение здесь (MSDN)
Работал отлично для меня, надеюсь, что это поможет кому-то еще.
- Добавить новый класс (файл MyTreeView.cs) в ваш проект и вставить код, показанный ниже.
- Скомпилировать.
- Отбросьте новый элемент управления под названием "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);
}
}
}
Ответ 8
Этот вариант ответа IronGeeks работает для меня и работает с жирным узлом:
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()
.