0

I am working with winforms in .NET 3.5 using c#. now i want to add treeview with parent nodes and checkboxes in child nodes...

I have completed parent node creation by following code..

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

Now I want to add checkboxes in child nodes..

Can you help me anyone?

Bala
  • 25
  • 1
  • 7

3 Answers3

1

Took me a day to find an appropriate solution: http://dotnetfollower.com/wordpress/2011/05/winforms-treeview-hide-checkbox-of-treenode/.

The solution is inheriting treeview and treenode with new classes, that you can use the new treenode class without a checkbox. An event added to handle the hidden checkbox.

below, are the classes copied from the link:

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

}

AJ AJ
  • 187
  • 2
  • 12
0

You can't have mixed checkbox states on the same TreeView as standard, it's either all or nothing. However, I dig a bit of digging around and found Disable TreeView Node Checkbox - It may help you out.

Community
  • 1
  • 1
laminatefish
  • 5,197
  • 5
  • 38
  • 70
0

If you want only children nodes have checkboxes, here is a solution:

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

To make it better, you may want to create your own TreeView, override OnDrawNode (with the same code as I posted above) and set DoubleBuffered=true in the constructor.

King King
  • 61,710
  • 16
  • 105
  • 130
  • a special thanks to u...but some issues are like, it doesn't shows + and - rectangles...is there any idea to solve it – Bala Jun 25 '13 at 08:53
  • @Bala I tested and it showed OK, could you give me some screen shot of your treeview (after applying my code)? – King King Jun 25 '13 at 10:07
  • i can't post an screen shot... called draw node function like below... for (int i = 0; i < dt.Rows.Count; i++) { } this.tvRoles.DrawNode += new DrawTreeNodeEventHandler(this.tvRoles_DrawNode); – Bala Jun 25 '13 at 10:38
  • @Bala you can post the link to your screen shot, that's how to post a screen shot for a newbie in SO. – King King Jun 25 '13 at 11:16
  • then these nodes are taken from database and i have to store a values for checked and not checked nodes in another table. so how can i find whether checked r not??? – Bala Jun 25 '13 at 11:59
  • @Bala I'm sorry for my incomplete solution, I corrected and it worked now, please see my code again, notice the difference at `d + e.Bounds.Top`, I missed the `e.Bounds.Top`, and the `CheckBoxes` of all the parent nodes are drawn at the same position of the first parent node, that's why you (and I) couldn't see the `CheckBoxes` of other parent nodes. :) – King King Jun 25 '13 at 13:02
  • @Bala check the `Node.Checked` property, you are enable to set or get that state (corresponding to the presence of a checked or unchecked CheckBox) – King King Jun 25 '13 at 13:15
  • @Bala I have email but don't use it much in communication, I just want to discuss in forums, to me, email is just a must have to register forums and submit to other forms on the net. – King King Jun 25 '13 at 14:26
  • i am having a doubt...is there any use by getting SO reputations.i meant is there any chance to get opportunity for my career development(foreign jobs). – Bala Jun 26 '13 at 10:28
  • @Bala study yourself and the chances will come, I don't really understand why you mentioned SO reputations here? – King King Jun 26 '13 at 10:30
  • thank you...some websites gives information's like this.so that only i had asked. – Bala Jun 26 '13 at 11:09
  • Since I'm not allowed to ask this question, I'll have to just comment here. Can anyone tell me if some easier way than actually drawing a checkbox has been implemented in .NET 4.5? The above method is incredibly tedious, messy and obviously Microsoft is leaving out something fairly essential in their SDK. – Nathan McKaskle Jan 28 '15 at 21:09