c# Winforms Treeview自定义复选框
本文关键字:复选框 自定义 Treeview Winforms | 更新日期: 2023-09-27 17:49:52
我正在开发一个实用程序,它可以帮助我构建长而重复的HTML表。我有从XML文件导入的数据、显示名称的listBox、将文本插入包含来自XML的某些数据的richTextBox的按钮,但是我必须为每个名称手动输入信息。
我有一个列出委员会(家长)和小组委员会(1级儿童)的树视图。我可以选中适当的框,单击一个按钮,然后创建所有相应的HTML。然而,每个委员会(和附属委员会)都有一名主席和一名高级成员。而不是在每个父节点和子节点下添加两个额外的节点——我有71个父节点和子节点。我宁愿不添加更多的142个节点-我希望有一种方法有"四点击"复选框…?第一次点击= checkmark;2 =绿色;3 =红色;4 =清除。或类似的。这样我就可以"检查"自己是否是成员,"双重检查"主席,"三重检查"排名,第四个人就可以从头开始了。
我也愿意接受其他方法的建议。这是我需要开始工作的最后一点,以节省我手工输入2-3K行HTML,所以我不在乎我是如何完成的。谢谢。
好了,不好意思,好久不见。你知道,生活之类的。总之,我最终创建了自己的TreeNode和TreeView类。这是我第一次使用WinForms,所以很多东西看起来都很挑剔。结果比我想象的要简单得多。如果有人想用这个,请自便。
Check*.bmp图像只是一个我上色的复选框。我可能会为此制作自己的四个图像,并整理populateStateImageList()方法。此外,我认为这将适用于您需要的尽可能多的状态,直到StateImageList的14个图像限制。
using System.Drawing;
using System.Windows.Forms;
namespace jkHTMLBuilder
{
public class QuadCheckTreeNode : TreeNode
{
public enum CheckState : int { UnChecked, Checked, Chair, Rank } // The four possible states
private CheckState _cs = CheckState.UnChecked; // The node's current state
public CheckState checkState
{
get
{
return _cs;
}
set
{
_cs = value;
}
}
public QuadCheckTreeNode(string initString) : base()
{
this.Text = initString;
this.checkState = CheckState.UnChecked;
this.Checked = false;
this.StateImageIndex = 0;
}
public void checkAdvance() // This is called from onAfterCheck to set the next consecutive state
{
switch (checkState)
{
case CheckState.UnChecked:
checkState = CheckState.Checked;
break;
case CheckState.Checked:
checkState = CheckState.Chair;
break;
case CheckState.Chair:
checkState = CheckState.Rank;
break;
case CheckState.Rank:
checkState = CheckState.UnChecked;
break;
}
this.Checked = (this.checkState == CheckState.UnChecked ? false : true);
}
}
class QuadCheckTreeView : TreeView
{
private bool clickStop = false;
private bool shouldAdvance = false;
public QuadCheckTreeView() : base()
{
StateImageList = new ImageList();
}
public void populateStateImageList() // I made this a separate method and call it from my Load_Senators method so the images are
{ // set up when the XML file is loaded. Apparently, loading the files ( Check*.bmmp )
for (int i = 0; i < 2; i++) // from the ctor causes problems...? Whatever. This works.
{
Bitmap bmp = new Bitmap(16, 16);
Graphics chkGraphics = Graphics.FromImage(bmp);
switch (i)
{
case 0:
CheckBoxRenderer.DrawCheckBox(chkGraphics, new Point(0, 1), System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal);
break;
case 1:
CheckBoxRenderer.DrawCheckBox(chkGraphics, new Point(0, 1), System.Windows.Forms.VisualStyles.CheckBoxState.CheckedNormal);
break;
}
StateImageList.Images.Add(bmp);
}
Bitmap myBitmap = new Bitmap("..''..''CheckBlue.bmp");
StateImageList.Images.Add(myBitmap);
myBitmap = new Bitmap("..''..''CheckRed.bmp");
StateImageList.Images.Add(myBitmap);
}
public void ClearNodes(TreeNodeCollection nodes) // This is for when I move on to the next record. Unchecks everything.
{
clickStop = true;
foreach (QuadCheckTreeNode qctn in nodes)
{
qctn.Checked = false;
qctn.checkState = QuadCheckTreeNode.CheckState.UnChecked;
if (qctn.Nodes.Count > 0)
{
foreach (QuadCheckTreeNode cqctn in qctn.Nodes)
{
cqctn.Checked = false;
cqctn.checkState = QuadCheckTreeNode.CheckState.UnChecked;
}
}
}
clickStop = false;
}
protected override void OnCreateControl()
{
base.OnCreateControl();
CheckBoxes = false; // Checkboxes off to use my images
ClearNodes(this.Nodes); // Probably not needed.
}
protected override void OnNodeMouseClick(TreeNodeMouseClickEventArgs e)
{
base.OnNodeMouseClick(e);
TreeViewHitTestInfo tvhtInfo = HitTest(e.X, e.Y); // If you didn't click on it, ignore.
if (tvhtInfo == null || tvhtInfo.Location !=
TreeViewHitTestLocations.StateImage)
{
return;
}
QuadCheckTreeNode qctn = (QuadCheckTreeNode)e.Node; // If you right-clicked, set to UnChecked
if (e.Button == MouseButtons.Right)
{
if (qctn.checkState != QuadCheckTreeNode.CheckState.UnChecked)
{
qctn.checkState = QuadCheckTreeNode.CheckState.UnChecked;
qctn.Checked = false;
shouldAdvance = false;
}
}
else
shouldAdvance = true; // Left click sets this var==true so the node's Advance() method is called
qctn.Checked = qctn.Checked; // This fires the onAfterCheck event
}
protected override void OnAfterCheck(TreeViewEventArgs e)
{
base.OnAfterCheck(e);
if (clickStop) // This keeps the event from running if it's called inappropriately
{
return;
}
clickStop = true;
QuadCheckTreeNode qctn = (QuadCheckTreeNode)e.Node;
if (shouldAdvance)
{
qctn.checkAdvance();
shouldAdvance = false;
qctn.StateImageIndex = (int)qctn.checkState;
}
checkParent(qctn); // Calling this method, if it actually checks a parent node, won't call onAfterCheck because of clickStop
clickStop = false;
}
protected void checkParent(QuadCheckTreeNode qctn)
{
QuadCheckTreeNode pqctn = (QuadCheckTreeNode)qctn.Parent;
if (pqctn == null)
return;
if (pqctn.checkState == QuadCheckTreeNode.CheckState.UnChecked) // This checks a parent if it has a checked child
{
bool chkParent = false;
foreach (QuadCheckTreeNode n in pqctn.Nodes)
{
if (n.checkState != QuadCheckTreeNode.CheckState.UnChecked) // Checks all the children. If even one is checked, the parent gets checked
chkParent = true;
}
if (chkParent)
{
pqctn.Checked = true;
pqctn.checkState = QuadCheckTreeNode.CheckState.Checked;
}
}
}
}
}