如何在子节点树视图中添加复选框
本文关键字:添加 复选框 视图 子节点 | 更新日期: 2023-09-27 18:19:49
我使用c#
在.NET 3.5
中处理winforms
。现在我想添加带有父节点和子节点中复选框的树视图。。。
我已经通过以下代码完成了父节点的创建。。
dt = conn.dataTable("select desgn from designation");
tvRoles.Nodes.Clear();
foreach (DataRow dr in dt.Rows)
{
TreeNode parent = new TreeNode();
parent.Text = dr[0].ToString();
string value = dr[0].ToString();
parent.Expand();
tvRoles.Nodes.Add(parent);
subLevel(parent, value);
}
现在我想在子节点中添加复选框。。
你能帮我吗?
我花了一天时间才找到合适的解决方案:http://dotnetfollower.com/wordpress/2011/05/winforms-treeview-hide-checkbox-of-treenode/.
解决方案是用新的类继承树视图和树节点,这样您就可以在不带复选框的情况下使用新的树节点类。为处理隐藏复选框而添加的事件。
下面是从链接复制的类:
/// <summary>
/// Represents a node with hidden checkbox
/// </summary>
public class HiddenCheckBoxTreeNode : TreeNode
{
public HiddenCheckBoxTreeNode() { }
public HiddenCheckBoxTreeNode(string text) : base(text) { }
public HiddenCheckBoxTreeNode(string text, TreeNode[] children) : base(text, children) { }
public HiddenCheckBoxTreeNode(string text, int imageIndex, int selectedImageIndex) : base(text, imageIndex, selectedImageIndex) { }
public HiddenCheckBoxTreeNode(string text, int imageIndex, int selectedImageIndex, TreeNode[] children) : base(text, imageIndex, selectedImageIndex, children) { }
protected HiddenCheckBoxTreeNode(SerializationInfo serializationInfo, StreamingContext context) : base(serializationInfo, context) { }
}
public class MixedCheckBoxesTreeView : TreeView
{
/// <summary>
/// Specifies the attributes of a node
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct TV_ITEM
{
public int Mask;
public IntPtr ItemHandle;
public int State;
public int StateMask;
public IntPtr TextPtr;
public int TextMax;
public int Image;
public int SelectedImage;
public int Children;
public IntPtr LParam;
}
public const int TVIF_STATE = 0x8;
public const int TVIS_STATEIMAGEMASK = 0xF000;
public const int TVM_SETITEMA = 0x110d;
public const int TVM_SETITEM = 0x110d;
public const int TVM_SETITEMW = 0x113f;
public const int TVM_GETITEM = 0x110C;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(HandleRef hWnd, int msg, int wParam, ref TV_ITEM lParam);
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
// trap TVM_SETITEM message
if (m.Msg == TVM_SETITEM || m.Msg == TVM_SETITEMA || m.Msg == TVM_SETITEMW)
// check if CheckBoxes are turned on
if (CheckBoxes)
{
// get information about the node
TV_ITEM tv_item = (TV_ITEM)m.GetLParam(typeof(TV_ITEM));
HideCheckBox(tv_item);
}
}
protected void HideCheckBox(TV_ITEM tv_item)
{
if (tv_item.ItemHandle != IntPtr.Zero)
{
// get TreeNode-object, that corresponds to TV_ITEM-object
TreeNode currentTN = TreeNode.FromHandle(this, tv_item.ItemHandle);
HiddenCheckBoxTreeNode hiddenCheckBoxTreeNode = currentTN as HiddenCheckBoxTreeNode;
// check if it's HiddenCheckBoxTreeNode and
// if its checkbox already has been hidden
if(hiddenCheckBoxTreeNode != null)
{
HandleRef treeHandleRef = new HandleRef(this, Handle);
// check if checkbox already has been hidden
TV_ITEM currentTvItem = new TV_ITEM();
currentTvItem.ItemHandle = tv_item.ItemHandle;
currentTvItem.StateMask = TVIS_STATEIMAGEMASK;
currentTvItem.State = 0;
IntPtr res = SendMessage(treeHandleRef, TVM_GETITEM, 0, ref currentTvItem);
bool needToHide = res.ToInt32() > 0 && (currentTvItem.State & currentTvItem.StateMask) != 0;
if (needToHide)
{
// specify attributes to update
TV_ITEM updatedTvItem = new TV_ITEM();
updatedTvItem.ItemHandle = tv_item.ItemHandle;
updatedTvItem.Mask = TVIF_STATE;
updatedTvItem.StateMask = TVIS_STATEIMAGEMASK;
updatedTvItem.State = 0;
// send TVM_SETITEM message
SendMessage(treeHandleRef, TVM_SETITEM, 0, ref updatedTvItem);
}
}
}
}
protected override void OnBeforeCheck(TreeViewCancelEventArgs e)
{
base.OnBeforeCheck(e);
// prevent checking/unchecking of HiddenCheckBoxTreeNode,
// otherwise, we will have to repeat checkbox hiding
if (e.Node is HiddenCheckBoxTreeNode)
e.Cancel = true;
}
}
如果只希望子节点有复选框,这里有一个解决方案:
//First, as I said, you have to set treeView.CheckBoxes = true;
//Second, set treeView.DrawMode = TreeViewDrawMode.OwnerDrawAll;
//Add this DrawNode event handler and enjoy =)
private void treeView_DrawNode(object sender, DrawTreeNodeEventArgs e)
{
if (e.Node.Parent == null)//If the Node is a Parent
{
int d = (int)(0.2*e.Bounds.Height);
Rectangle rect = new Rectangle(d + treeView.Margin.Left, d + e.Bounds.Top, e.Bounds.Height - d*2, e.Bounds.Height - d*2);
e.Graphics.FillRectangle(new SolidBrush(Color.FromKnownColor(KnownColor.Control)), rect);
e.Graphics.DrawRectangle(Pens.Silver, rect);
StringFormat sf = new StringFormat() { LineAlignment = StringAlignment.Center, Alignment = StringAlignment.Center };
e.Graphics.DrawString(e.Node.IsExpanded ? "-" : "+", treeView.Font, new SolidBrush(Color.Blue), rect, sf);
//Draw the dotted line connecting the expanding/collapsing button and the node Text
using (Pen dotted = new Pen(Color.Black) {DashStyle = System.Drawing.Drawing2D.DashStyle.Dot})
{
e.Graphics.DrawLine(dotted, new Point(rect.Right + 1, rect.Top + rect.Height / 2), new Point(rect.Right + 4, rect.Top + rect.Height / 2));
}
//Draw text
sf.Alignment = StringAlignment.Near;
Rectangle textRect = new Rectangle(e.Bounds.Left + rect.Right + 4, e.Bounds.Top, e.Bounds.Width - rect.Right - 4, e.Bounds.Height);
if (e.Node.IsSelected)
{
SizeF textSize = e.Graphics.MeasureString(e.Node.Text, treeView.Font);
e.Graphics.FillRectangle(new SolidBrush(SystemColors.Highlight), new RectangleF(textRect.Left, textRect.Top, textSize.Width, textRect.Height));
}
e.Graphics.DrawString(e.Node.Text, treeView.Font, new SolidBrush(treeView.ForeColor), textRect,sf);
}
else e.DrawDefault = true;
}
为了做得更好,您可能需要创建自己的TreeView
,覆盖OnDrawNode
(使用与我上面发布的代码相同的代码),并在构造函数中设置DoubleBuffered=true
。
在同一个TreeView上不能有标准的混合复选框状态,要么全有要么全无。然而,我四处挖掘,发现禁用TreeView节点复选框-它可能会帮助你。