如何在childnodes treeview中添加复选框?

时间:2013-06-25 06:23:59

标签: c# winforms

我正在winforms使用.NET 3.5使用c#。现在我想在父节点和子节点中的复选框中添加treeview ...

我已通过以下代码完成父节点创建。

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);
}

现在我想在子节点中添加复选框..

你能帮助我吗?

3 个答案:

答案 0 :(得分:1)

我花了一天时间找到合适的解决方案: http://dotnetfollower.com/wordpress/2011/05/winforms-treeview-hide-checkbox-of-treenode/

解决方案是使用新类继承treeview和treenode,您可以使用新的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;
}

}

答案 1 :(得分:0)

您不能在同一TreeView上使用混合复选框状态作为标准,它可以是全部或全部。但是,我挖了一些挖掘并发现Disable TreeView Node Checkbox - 它可能会帮助你。

答案 2 :(得分:0)

如果您只希望子节点有复选框,这是一个解决方案:

//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