* UITreeView: CheckBoxes增加三态,感谢群友:笑口常开

This commit is contained in:
Sunny 2021-08-26 10:27:53 +08:00
parent 37aacb0c13
commit 013b5084e1
7 changed files with 233 additions and 129 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -20,14 +20,18 @@
* 2020-07-07: V2.2.6 CheckBoxes等 * 2020-07-07: V2.2.6 CheckBoxes等
* 2020-08-12: V2.2.7 * 2020-08-12: V2.2.7
* 2021-07-19: V3.0.5 CheckBoxes时图片位置 * 2021-07-19: V3.0.5 CheckBoxes时图片位置
* 2021-08-26: V3.0.6 CheckBoxes增加三态
******************************************************************************/ ******************************************************************************/
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Data;
using System.Drawing; using System.Drawing;
using System.Drawing.Design; using System.Drawing.Design;
using System.Drawing.Drawing2D; using System.Drawing.Drawing2D;
using System.Linq;
using System.Windows.Forms; using System.Windows.Forms;
namespace Sunny.UI namespace Sunny.UI
@ -698,12 +702,13 @@ namespace Sunny.UI
{ {
base.OnDrawNode(e); base.OnDrawNode(e);
if (e.Node == null) return; if (e.Node == null || Nodes.Count == 0) return;
try
{
if (BorderStyle == BorderStyle.Fixed3D) BorderStyle = BorderStyle.FixedSingle; if (BorderStyle == BorderStyle.Fixed3D) BorderStyle = BorderStyle.FixedSingle;
if (e.Node == null || e.Node.Bounds.Width <= 0 && e.Node.Bounds.Height <= 0 && e.Node.Bounds.X <= 0 && if (e.Node == null || e.Node.Bounds.Width <= 0 && e.Node.Bounds.Height <= 0 && e.Node.Bounds.X <= 0 && e.Node.Bounds.Y <= 0)
e.Node.Bounds.Y <= 0)
{ {
e.DrawDefault = true; e.DrawDefault = true;
} }
@ -729,6 +734,8 @@ namespace Sunny.UI
} }
var checkboxColor = ForeColor; var checkboxColor = ForeColor;
if (e.Node != null)
{
if (e.Node == SelectedNode) if (e.Node == SelectedNode)
{ {
e.Graphics.FillRectangle((e.State & TreeNodeStates.Hot) != 0 ? HoverColor : SelectedColor, e.Graphics.FillRectangle((e.State & TreeNodeStates.Hot) != 0 ? HoverColor : SelectedColor,
@ -768,12 +775,12 @@ namespace Sunny.UI
if (CheckBoxes) if (CheckBoxes)
{ {
if (!e.Node.Checked) if (!e.Node.Checked)
using (var pn = new Pen(checkboxColor, 1))
{ {
e.Graphics.DrawRectangle(pn, e.Graphics.DrawRectangle(checkboxColor,
new Rectangle(checkBoxLeft + 2, e.Bounds.Y + (ItemHeight - 12) / 2 - 1, 12, 12)); new Rectangle(checkBoxLeft + 2, e.Bounds.Y + (ItemHeight - 12) / 2 - 1, 12, 12));
} }
else else
{
using (var pn = new Pen(checkboxColor, 2)) using (var pn = new Pen(checkboxColor, 2))
{ {
var pt1 = new Point(checkBoxLeft + 2 + 2, e.Bounds.Y + (ItemHeight - 12) / 2 - 1 + 5); var pt1 = new Point(checkBoxLeft + 2 + 2, e.Bounds.Y + (ItemHeight - 12) / 2 - 1 + 5);
@ -790,10 +797,27 @@ namespace Sunny.UI
} }
} }
if (!DicNodeStatus.Keys.Contains(e.Node.GetHashCode()))
{
DicNodeStatus.Add(e.Node.GetHashCode(), false);
}
if (DicNodeStatus[e.Node.GetHashCode()])
{
var location = e.Node.Bounds.Location;
location.Offset(-29, 10);
var size = new Size(7, 7);
e.Graphics.FillRectangle(checkboxColor, new Rectangle(location, size)); //这里绘制的是正方形
}
}
}
var lineY = e.Bounds.Y + e.Node.Bounds.Height / 2 - 1; var lineY = e.Bounds.Y + e.Node.Bounds.Height / 2 - 1;
var lineX = 3 + e.Node.Level * Indent + 9; var lineX = 3 + e.Node.Level * Indent + 9;
if (ShowLinesEx) if (ShowLinesEx)
{
try try
{ {
//绘制虚线 //绘制虚线
@ -812,16 +836,21 @@ namespace Sunny.UI
{ {
lineX -= Indent; lineX -= Indent;
if (pNode != null && Nodes.Count > 0)
{
if (pNode.NextNode != null) if (pNode.NextNode != null)
e.Graphics.DrawLine(pn, lineX, lineY, lineX, e.Node.Bounds.Top); e.Graphics.DrawLine(pn, lineX, lineY, lineX, e.Node.Bounds.Top);
if (pNode.NextNode != null) if (pNode.NextNode != null)
e.Graphics.DrawLine(pn, lineX, lineY, lineX, e.Node.Bounds.Bottom); e.Graphics.DrawLine(pn, lineX, lineY, lineX, e.Node.Bounds.Bottom);
}
pNode = pNode.Parent; pNode = pNode.Parent;
} }
} }
else else
{
if (e.Node != null && Nodes.Count > 0)
{ {
if (e.Node.PrevNode != null) if (e.Node.PrevNode != null)
e.Graphics.DrawLine(pn, lineX, lineY, lineX, e.Node.Bounds.Top); e.Graphics.DrawLine(pn, lineX, lineY, lineX, e.Node.Bounds.Top);
@ -829,6 +858,7 @@ namespace Sunny.UI
if (e.Node.NextNode != null) if (e.Node.NextNode != null)
e.Graphics.DrawLine(pn, lineX, lineY, lineX, e.Node.Bounds.Bottom); e.Graphics.DrawLine(pn, lineX, lineY, lineX, e.Node.Bounds.Bottom);
} }
}
pn.Dispose(); pn.Dispose();
} }
@ -836,6 +866,7 @@ namespace Sunny.UI
{ {
Console.WriteLine(exception); Console.WriteLine(exception);
} }
}
lineX = 3 + e.Node.Level * Indent + 9; lineX = 3 + e.Node.Level * Indent + 9;
//绘制左侧+号 //绘制左侧+号
@ -849,6 +880,11 @@ namespace Sunny.UI
} }
} }
} }
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private bool TreeNodeSelected(DrawTreeNodeEventArgs e) private bool TreeNodeSelected(DrawTreeNodeEventArgs e)
{ {
@ -867,6 +903,74 @@ namespace Sunny.UI
base.WndProc(ref m); base.WndProc(ref m);
} }
private Dictionary<int, bool> DicNodeStatus = new Dictionary<int, bool>();
protected override void OnAfterCheck(TreeViewEventArgs e)
{
base.OnAfterCheck(e);
if (e.Action == TreeViewAction.ByMouse) //鼠标点击
{
DicNodeStatus[e.Node.GetHashCode()] = false;
SetChildNodeCheckedState(e.Node, e.Node.Checked);
if (e.Node.Parent != null)
{
SetParentNodeCheckedState(e.Node);
}
}
}
private void SetParentNodeCheckedState(TreeNode currNode)
{
TreeNode parentNode = currNode.Parent; //获得当前节点的父节点
var count = parentNode.Nodes.Cast<TreeNode>().Where(n => n.Checked).ToList().Count;
parentNode.Checked = count == parentNode.Nodes.Count;
var half = parentNode.Nodes.Cast<TreeNode>().Where(n => DicNodeStatus[n.GetHashCode()]).ToList().Count;
if ((count > 0 && count < parentNode.Nodes.Count) || half > 0)
{
DicNodeStatus[parentNode.GetHashCode()] = true;
}
else
{
DicNodeStatus[parentNode.GetHashCode()] = false;
}
var g = CreateGraphics();
OnDrawNode(new DrawTreeNodeEventArgs(g, parentNode,
new Rectangle(0, parentNode.Bounds.Y, Width, parentNode.Bounds.Height), TreeNodeStates.Hot));
g.Dispose();
if (parentNode.Parent != null) //如果父节点之上还有父节点
{
SetParentNodeCheckedState(parentNode); //递归调用
}
}
//选中节点之后,选中节点的所有子节点
private void SetChildNodeCheckedState(TreeNode currNode, bool state)
{
TreeNodeCollection nodes = currNode.Nodes; //获取所有子节点
if (nodes.Count > 0) //存在子节点
{
foreach (TreeNode tn in nodes)
{
DicNodeStatus[tn.GetHashCode()] = false;
tn.Checked = state;
SetChildNodeCheckedState(tn, state);//递归调用子节点的子节点
}
}
}
} }
} }
} }

View File

@ -21,7 +21,7 @@
* 2021-06-20: V3.0.4 UITitlePage * 2021-06-20: V3.0.4 UITitlePage
* 2021-07-18: V3.0.5 OnLoad在加载时重复加载两次的问题Final函数退 * 2021-07-18: V3.0.5 OnLoad在加载时重复加载两次的问题Final函数退
* 2021-08-17: V3.0.6 TitleFont属性 * 2021-08-17: V3.0.6 TitleFont属性
* 2021-08-24: V3.0.3 OnLoad在加载时重复加载两次的问题 * 2021-08-24: V3.0.6 OnLoad在加载时重复加载两次的问题
******************************************************************************/ ******************************************************************************/
using System; using System;