* UITreeView: CheckBoxes增加三态,感谢群友:笑口常开
This commit is contained in:
parent
37aacb0c13
commit
013b5084e1
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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);//递归调用子节点的子节点
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user