Han Tran
Han Tran

Reputation: 2093

Cannot set icon for node of treeview

I have a treeview and a imageList which contain 1 icon (folder.ico), I want to set icon only for root node, child node will don't have icon, so I try to set image index for child node but it have some problem, look the picture: enter image description here

My code:

        ImageList imageList = new ImageList();
        imageList.Images.Add(Image.FromFile(System.AppDomain.CurrentDomain.BaseDirectory.Replace("\\bin\\Debug\\","") + "\\Images\\folder.ico"), Color.Transparent);
        treeView1.ImageList = imageList;
        foreach (TreeNode node in treeView1.Nodes)
        {
            foreach (TreeNode node2 in node.Nodes)
            {
                node2.ImageIndex = 100;
                node2.SelectedImageIndex = 100;
            }
        }

Thanks

EDIT I create a Custom TreeView at the answer of @Killercam:

class CustomTreeView : TreeView
{
public const int NOIMAGE = -1;

public CustomTreeView()
    : base()
{
    // .NET Bug: Unless LineColor is set, Win32 treeview returns -1 (default), .NET returns Color.Black!
    base.LineColor = SystemColors.GrayText;
    base.DrawMode = TreeViewDrawMode.OwnerDrawAll;
}

protected override void OnDrawNode(DrawTreeNodeEventArgs e)
{
    // Space between Image and Label.
    const int SPACE_IL = 3;  

    // We only do additional drawing.
    e.DrawDefault = true;
    base.OnDrawNode(e);
    if (base.ShowLines && base.ImageList != null && e.Node.ImageIndex == NOIMAGE
        // exclude root nodes, if root lines are disabled
        //&& (base.ShowRootLines || e.Node.Level > 0))
            )
    {
        // Using lines & images, but this node has none: fill up missing treelines

        // Image size
        int imgW = base.ImageList.ImageSize.Width;
        int imgH = base.ImageList.ImageSize.Height;

        // Image center
        int xPos = e.Node.Bounds.Left - SPACE_IL - imgW / 2;
        int yPos = (e.Node.Bounds.Top + e.Node.Bounds.Bottom) / 2;

        // Image rect
        Rectangle imgRect = new Rectangle(xPos, yPos, 0, 0);
        imgRect.Inflate(imgW / 2, imgH / 2);

        using (Pen p = new Pen(base.LineColor, 1))
        {
            p.DashStyle = DashStyle.Dot;

            // Account uneven Indent for both lines.
            p.DashOffset = base.Indent % 2;

            // Horizontal treeline across width of image
            // account uneven half of delta ItemHeight & ImageHeight.
            int yHor = yPos + ((base.ItemHeight - imgRect.Height) / 2) % 2;

            //if (base.ShowRootLines || e.Node.Level > 0)
            //{
            //    e.Graphics.DrawLine(p, imgRect.Left, yHor, imgRect.Right, yHor);
            //}
            //else
            //{
            //    // for root nodes, if root lines are disabled, start at center
            //    e.Graphics.DrawLine(p, xPos - (int)p.DashOffset, yHor, imgRect.Right, yHor);
            //}

            e.Graphics.DrawLine(p,
                    (base.ShowRootLines || e.Node.Level > 0) ? imgRect.Left : xPos - (int)p.DashOffset,
                    yHor, imgRect.Right, yHor);
            if (!base.CheckBoxes && e.Node.IsExpanded)
            {
                // Vertical treeline , offspring from NodeImage center to e.Node.Bounds.Bottom
                // yStartPos: account uneven Indent and uneven half of delta ItemHeight & ImageHeight
                int yVer = yHor + (int)p.DashOffset;
                e.Graphics.DrawLine(p, xPos, yVer, xPos, e.Node.Bounds.Bottom);
            }
        }
    }
}

protected override void OnAfterCollapse(TreeViewEventArgs e)
{
    base.OnAfterCollapse(e);
    if (!base.CheckBoxes && base.ImageList != null && e.Node.ImageIndex == NOIMAGE)
    {
        // DrawNode event not raised: redraw node with collapsed treeline
        base.Invalidate(e.Node.Bounds);
    }
}
}

Then use it in my code:

private void TestCustomTreeView_Load(object sender, EventArgs e)
    {
        // @Killercam EDIT: Set the default Image to one that is not used.
        valForm.siteTreeView.ImageIndex = 100;
        valForm.siteTreeView.SelectedImageIndex = 100;

        TemplateCustomTreeView myTree = new TemplateCustomTreeView();
        myTree.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));

        myTree.Location = new System.Drawing.Point(6, 26);
        myTree.Name = "tree";
        myTree.Scrollable = true;
        myTree.Size = new System.Drawing.Size(320, 296);
        myTree.ImageList = imageList1;
        /*Add item*/
        TreeNode node = new TreeNode();
        node.Name = "abc1";
        node.Text = "abc1";
        node.ImageIndex = 0;
        myTree.Nodes.Add(node);
        TreeNode node3 = new TreeNode();
        node3.Name = "abc2";
        node3.Text = "abc2";
        node3.ImageIndex = -1;            
        node.Nodes.Add(node3);
        ////
        TreeNode node2 = new TreeNode();
        node2.Name = "abc3";
        node2.Text = "abc3";
        node2.ImageIndex = 0;
        myTree.Nodes.Add(node2);
        this.Controls.AddRange(new System.Windows.Forms.Control[] { myTree });

    }
}

The result still not work, It's still have a folder icon before the text! enter image description here

Upvotes: 2

Views: 11585

Answers (3)

NNM
NNM

Reputation: 13

Tried using a blank image file?

(Or one that only contains the horizontal stippled line, or an arrow...)

Upvotes: 0

MoonKnight
MoonKnight

Reputation: 23831

You can't do what you require

"All I want is don't show icon at child node."

without overriding the control. I also have found that you cannot display different images for different nodes with the standard WinForms TreeView. Below is some code that will make the TreeView look better; that is will draw the small section of the tree line for the sub-nodes.

class CustomTreeView : TreeView
{
    public const int NOIMAGE = -1;

    public CustomTreeView()
        : base()
    {
        // .NET Bug: Unless LineColor is set, Win32 treeview returns -1 (default), .NET returns Color.Black!
        base.LineColor = SystemColors.GrayText;
        base.DrawMode = TreeViewDrawMode.OwnerDrawAll;
    }

    protected override void OnDrawNode(DrawTreeNodeEventArgs e)
    {
        // Space between Image and Label.
        const int SPACE_IL = 3;  

        // We only do additional drawing.
        e.DrawDefault = true;
        base.OnDrawNode(e);
        if (base.ShowLines && base.ImageList != null && e.Node.ImageIndex == NOIMAGE
            // exclude root nodes, if root lines are disabled
            //&& (base.ShowRootLines || e.Node.Level > 0))
                )
        {
            // Using lines & images, but this node has none: fill up missing treelines

            // Image size
            int imgW = base.ImageList.ImageSize.Width;
            int imgH = base.ImageList.ImageSize.Height;

            // Image center
            int xPos = e.Node.Bounds.Left - SPACE_IL - imgW / 2;
            int yPos = (e.Node.Bounds.Top + e.Node.Bounds.Bottom) / 2;

            // Image rect
            Rectangle imgRect = new Rectangle(xPos, yPos, 0, 0);
            imgRect.Inflate(imgW / 2, imgH / 2);

            using (Pen p = new Pen(base.LineColor, 1))
            {
                p.DashStyle = DashStyle.Dot;

                // Account uneven Indent for both lines.
                p.DashOffset = base.Indent % 2;

                // Horizontal treeline across width of image
                // account uneven half of delta ItemHeight & ImageHeight.
                int yHor = yPos + ((base.ItemHeight - imgRect.Height) / 2) % 2;

                //if (base.ShowRootLines || e.Node.Level > 0)
                //{
                //    e.Graphics.DrawLine(p, imgRect.Left, yHor, imgRect.Right, yHor);
                //}
                //else
                //{
                //    // for root nodes, if root lines are disabled, start at center
                //    e.Graphics.DrawLine(p, xPos - (int)p.DashOffset, yHor, imgRect.Right, yHor);
                //}

                e.Graphics.DrawLine(p,
                        (base.ShowRootLines || e.Node.Level > 0) ? imgRect.Left : xPos - (int)p.DashOffset,
                        yHor, imgRect.Right, yHor);
                if (!base.CheckBoxes && e.Node.IsExpanded)
                {
                    // Vertical treeline , offspring from NodeImage center to e.Node.Bounds.Bottom
                    // yStartPos: account uneven Indent and uneven half of delta ItemHeight & ImageHeight
                    int yVer = yHor + (int)p.DashOffset;
                    e.Graphics.DrawLine(p, xPos, yVer, xPos, e.Node.Bounds.Bottom);
                }
            }
        }
    }

    protected override void OnAfterCollapse(TreeViewEventArgs e)
    {
        base.OnAfterCollapse(e);
        if (!base.CheckBoxes && base.ImageList != null && e.Node.ImageIndex == NOIMAGE)
        {
            // DrawNode event not raised: redraw node with collapsed treeline
            base.Invalidate(e.Node.Bounds);
        }
    }
}

This will give you a TreeView that looks like:

CustomTreeView

Here my master node (Node[0]) is the one without a specified Image and is what you require for your File1/File2 nodes.

I hope this helps.

Upvotes: 2

eyossi
eyossi

Reputation: 4340

Currently you created an images list with only one image (at index 0)

the line treeView1.ImageList = imageList; links that list to the treeview

the line node2.ImageIndex = 100; links the image at index 100 (that doesn't exist) on that list to be displayed

you have only one image in the list, that means you have an image only at index 0.

so try that:

node2.ImageIndex = 0;
node2.SelectedImageIndex = 0;

Upvotes: 1

Related Questions