如何在子节点树视图中添加复选框

本文关键字:添加 复选框 视图 子节点 | 更新日期: 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节点复选框-它可能会帮助你。