博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
定制TreeView控件,实现节点样式自定义及节点级别的单选、复选(转)
阅读量:4679 次
发布时间:2019-06-09

本文共 6279 字,大约阅读时间需要 20 分钟。

需求

在项目中需要对TreeView进行定制,要求比较简单,主要要求如下:

  1.  每个节点被造中时可以有自己的事件
  2. Winform中TreeView控件默认只支持树级别的CheckBox,再要求支持节点级别的CheckBox/RadioButton,即能为每个节点设置支不支持选择,选择的样式是复选还是单选。
  3. Winform中TreeView控件节点的默认显示样式是“CheckBox"+ “图片”+“节点文字”,现要求互换“CheckBox”和“图片”的位置,显示样式改为“图片”+“CheckBox”+“节点文字”。

总体显示效果如下图:

设计思路

TreeView控件有属 性,我们需要定义一个继承自TreeView的类(这里叫GTreeView吧),并在GTreeView的构造函数里设置DrawMode =TreeViewDrawMode .OwnerDrawText,以告诉系统我们需要自己绘制文字。然后在GTreeView的DrawNode事件中根据GTreeNode的 CheckBoxVisible,CheckBoxStyle属性来先绘制选择框,这里的选择框实际上是一个图片,根据属性的不同决定是不绘制还是绘制 RadioButtonChecked/RadioButtonUnchecked/CheckBoxChecked /CheckBoxUnchecked中的一个,绘制完图片后再绘制节点文本。

GTreeNode继承于TreeNode,主要添加了CheckBoxVisible, CheckBoxStyle属性和NodeSelected事件,新增加属性和事件的用途见名知义,不多解释。

Override TreeView的MouseUp事件,判断如果Mouse落后在选择框图片内,则改变节点的选中状态并重绘树,需要注意如果是单选节点的话还需要清空兄弟节点的选中状态,因为同一个父节点下只允许一个单选节点为选中状态。

Override TreeView的AfterSelected事件,如果当前选中的节点有NodeSelected EventHanlder则直接调用并返回,否则调用AfterSelected的默认处理。

代码

TreeView Code
using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using CustomTreeView.Properties; namespace GADPlatSystem.Tools {
/// /// 自定义TreeView控件,支持节点级别的复选、单选; /// 节点显示样式改为Icon+CheckBox+NodeText的样式 /// publicclass GTreeView : TreeView {
#region Private Variables privateconstint checkBoxImageWidth =16; privateconstint checkBoxImageHeight =16; private Image imgChecked; private Image imgUnchecked; private Image imgRBChecked; private Image imgRBUnchecked; private System.ComponentModel.IContainer components; #endregion #region Constructs public GTreeView() {
InitializeComponent(); // 初始化CheckBox相关的图片 imgUnchecked = Resource.TreeNodeUnchecked; imgChecked = Resource.TreeNodeChecked; imgRBUnchecked = Resource.TreeNodeRBUnchecked; imgRBChecked = Resource.TreeNodeRBChecked; // 设置TreeView为自己绘制文本和图标并绑定相关的事件 this.DrawMode = TreeViewDrawMode.OwnerDrawText; this.DrawNode +=new DrawTreeNodeEventHandler(GTreeView_DrawNode); this.MouseUp +=new MouseEventHandler(GTreeView_MouseUp); } #endregion #region Event Hanlder Methods /// /// 判断如果点击的是Checkbox图片,则改变节点的IsCheck属性值 /// 需要注意的是同一父节点下只允许一个RadioButton类型的节点为选中状态 /// /// /// void GTreeView_MouseUp(object sender, MouseEventArgs e) {
GTreeNode node = GetNodeAt(e.X, e.Y) as GTreeNode; if (node ==null||!node.CheckBoxVisible) {
return; } Rectangle checkboxImgRect =new Rectangle(node.Bounds.X, node.Bounds.Y, checkBoxImageWidth, checkBoxImageHeight); //节点区域 // 如果点击的是checkbox图片 if (checkboxImgRect.Contains(e.X, e.Y)) {
node.Checked =!node.Checked; // 如果是单选,则设置同级别的其它单选项为unchecked. if (node.Parent !=null&& node.CheckBoxStyle == GTreeNode.CheckBoxStyleEnum.RadioButton) {
foreach (TreeNode siblingNode in node.Parent.Nodes) {
var siblingGNode = siblingNode as GTreeNode; if (siblingGNode ==null) {
continue; } if (siblingGNode.Name != node.Name && siblingGNode.CheckBoxStyle == GTreeNode.CheckBoxStyleEnum.RadioButton && siblingGNode.Checked) {
siblingGNode.Checked =false; } } } } } /// /// 绘制节点的图标和文字,样式为Icon+CheckBox+NodeText /// Checkbox支持节点级别的单选、复选 /// /// /// void GTreeView_DrawNode(object sender, DrawTreeNodeEventArgs e) {
GTreeNode node = e.Node as GTreeNode; if (node ==null) {
return; } Rectangle nodeRect = e.Node.Bounds; // 如果需要显示CheckBox,则绘制 if (node.CheckBoxVisible) {
Point drawPt =new Point(nodeRect.Location.X, nodeRect.Location.Y); //绘制图标的起始位置 Size imgSize =new Size(checkBoxImageWidth, checkBoxImageHeight); //图片大小 Rectangle imgRect =new Rectangle(drawPt, imgSize); if (e.Node.Checked) {
if (node.CheckBoxStyle == GTreeNode.CheckBoxStyleEnum.CheckBox) {
e.Graphics.DrawImage(imgChecked, imgRect); } else {
e.Graphics.DrawImage(imgRBChecked, imgRect); } } else {
if (node.CheckBoxStyle == GTreeNode.CheckBoxStyleEnum.CheckBox) {
e.Graphics.DrawImage(imgUnchecked, imgRect); } else {
e.Graphics.DrawImage(imgRBUnchecked, imgRect); } } } //-----------------------绘制文本 ------------------------------- Rectangle textRec; if (node.CheckBoxVisible) {
textRec =new Rectangle(nodeRect.X + checkBoxImageWidth +2, nodeRect.Y, nodeRect.Width, nodeRect.Height); } else {
textRec = nodeRect; } Font nodeFont = e.Node.NodeFont; if (nodeFont ==null) nodeFont = ((TreeView)sender).Font; Brush textBrush = SystemBrushes.WindowText; if ((e.State & TreeNodeStates.Focused) !=0) {
e.Graphics.FillRectangle(SystemBrushes.Highlight, textRec); } e.Graphics.DrawString(e.Node.Text, nodeFont, textBrush, Rectangle.Inflate(textRec, 2, 0)); } /// /// 节点被选中后,如果节点有事件处理程序,则调用 /// /// protectedoverridevoid OnAfterSelect(TreeViewEventArgs e) {
var gNode = e.Node as GTreeNode; if (gNode !=null&& gNode.NodeSelected !=null) {
TreeViewEventArgs arg =new TreeViewEventArgs(e.Node); gNode.NodeSelected(this, arg); return; } base.OnAfterSelect(e); } #endregion #region Private Methods privatevoid InitializeComponent() {
this.SuspendLayout(); // // GTreeView // this.LineColor = System.Drawing.Color.Black; this.ResumeLayout(false); } #endregion } }

转载于:https://www.cnblogs.com/genghechuang/archive/2011/10/27/2226018.html

你可能感兴趣的文章
团队作业
查看>>
如何避免在简单业务逻辑上面的细节上面出错
查看>>
大型网站高并发的架构演变图-摘自网络
查看>>
8丶运行及总结
查看>>
WebApi请求原理
查看>>
[Node.js] node-persist: localStorage on the server
查看>>
jquery.event 研究学习之bind篇
查看>>
LOJ #108. 多项式乘法
查看>>
libusb开发指南
查看>>
SAS基础 -- 逻辑库不存在问题解决
查看>>
Servlet监听器统计在线人数
查看>>
关于手机端IOS系统微信中虚拟键盘遮挡input输入框问题的解决方案 草稿
查看>>
Python--小功能应用
查看>>
[linux-内核][转]内核日志及printk结构浅析
查看>>
程序猿的爱情-2012-01-22
查看>>
CentOS7.2 安装iptables
查看>>
网络是怎样连接的—1.浏览器生成消息
查看>>
codevs1430 素数判定
查看>>
2017年6月2号课堂笔记
查看>>
poj1015【DP.......无奈了】
查看>>