How do I set an image for some but not all nodes in a TreeView?
Asked Answered
A

7

22

I have a TreeView windows forms control with an ImageList, and I want some of the nodes to display images, but the others to not have images.

I don't want a blank space where the image should be. I don't want an image that looks like the lines that the TreeView would draw if it didn't have an ImageList. How do I get it to draw images for some items and not others, without resorting to clumsy hacks like that?

Animation answered 4/11, 2008 at 12:4 Comment(2)
Could you specify if this is used in a web or winforms app, please?Capsulize
Accepted answer should be the one by Aussie Ash, below. Tested, and it works.Burst
L
8

I tried this once and I don't think it is possible.

If you try to set both ImageKey and ImageIndex to "not set" values the control just defaults ImageIndex to 0. The following code:

treeView.ImageKey = "Value";
Debug.WriteLine(treeView.ImageIndex);
treeView.ImageKey = null;
Debug.WriteLine(treeView.ImageIndex);
treeView.ImageIndex = -1;
Debug.WriteLine(treeView.ImageIndex);

Produces output:

-1
0
0

This kind of tells you that the control developers wanted to make sure that there was always a default image. That just leaves you with the hack options I'm afraid.

Langbehn answered 4/11, 2008 at 16:36 Comment(2)
Thats because the treeView.ImageIndex setter contains this (I used ILSpy): if (value == -1)value = 0;if (value < 0)throw new ArgumentOutOfRangeException("ImageIndex", SR.GetString("InvalidLowBoundArgumentEx", new object[]{"ImageIndex",value.ToString(CultureInfo.CurrentCulture),0.ToString(CultureInfo.CurrentCulture)})); ....Elliotelliott
Just include a blank 1 pixel x 1 pixel icon and load the nodes that you don't want an icon, with this.Slalom
I
12

You need to set ImageIndex and SelectedImageIndex to a number that is higher than the number of values in your ImageList. For example, if you create this node and add it to your TreeView:

TreeNode node1 = new TreeNode(string.Empty, 12, 12); // imageList1.Count = 5

you will have an invisible TreeNode inserted into your TreeView. I changed the background color of my TreeView and it was still invisible.

(I googled this for some time, and I eventually found the answer here: http://www.tech-archive.net/Archive/DotNet/microsoft.public.dotnet.framework.windowsforms/2006-09/msg00322.html)

Indoaryan answered 17/6, 2009 at 20:55 Comment(2)
Is this documented by MS somewhere? I would be cautious using this kind of technique as is sounds like the kind of thing that may not be kept compatible in future versions of the framework.Langbehn
Invisible nodes are not very useful. If there is text, you'll see that the space for the image is still reserved, blank or not.Raphaelraphaela
D
12

I found that using StateImageList on the TreeView instead of ImageList will only show the image when StateImageIndex on the TreeNode is equal or greater than 0

Detain answered 20/7, 2015 at 1:55 Comment(2)
It seems to be limited to 14 images.Ainsworth
Brilliant yet simple workaround (if you only need <= 15 icons)Unpredictable
S
11

What I have chosen to do is to use an image of dots for those TreeView nodes that are not supposed to have an image.

TreeNode with image dots

I add this image as the last image in the list, and if the item is not supposed to have an image I set it to ImageList.Images.Count-1

Stutter answered 16/12, 2013 at 16:49 Comment(4)
I don't suppose you have this image somewhere do you? :-)Evidence
Take a screen shot and modify it to suit your purposeStutter
That is what I ended up doing, was just being lazy in case you had one lying around :-)Evidence
For future reference, I made a little GitHub project with instructions and an image (16x16) to do this:github.com/cmbankester/tree-view-no-image-dots/blob/master/…Larios
L
8

I tried this once and I don't think it is possible.

If you try to set both ImageKey and ImageIndex to "not set" values the control just defaults ImageIndex to 0. The following code:

treeView.ImageKey = "Value";
Debug.WriteLine(treeView.ImageIndex);
treeView.ImageKey = null;
Debug.WriteLine(treeView.ImageIndex);
treeView.ImageIndex = -1;
Debug.WriteLine(treeView.ImageIndex);

Produces output:

-1
0
0

This kind of tells you that the control developers wanted to make sure that there was always a default image. That just leaves you with the hack options I'm afraid.

Langbehn answered 4/11, 2008 at 16:36 Comment(2)
Thats because the treeView.ImageIndex setter contains this (I used ILSpy): if (value == -1)value = 0;if (value < 0)throw new ArgumentOutOfRangeException("ImageIndex", SR.GetString("InvalidLowBoundArgumentEx", new object[]{"ImageIndex",value.ToString(CultureInfo.CurrentCulture),0.ToString(CultureInfo.CurrentCulture)})); ....Elliotelliott
Just include a blank 1 pixel x 1 pixel icon and load the nodes that you don't want an icon, with this.Slalom
S
3

This will draw the TreeNode text where the image should have been, getting rid of the white space.

You'll need to set the TreeView's DrawMode property to OwnerDrawText. You can find the DrawMode property in the properties panel.

Next when you add a node, set it's ImageIndex and SelectedImageIndex greater than the value of your yourImageListName.Images.Count value. This is so no image will be drawn, but there will still be that white space you don't want.

Now to get rid the white space. Add a handle for the treeviews DrawNode event. This can be done by going to the treeviews property panel and clicking the Icon in the panel that looks like a lighting bolt, then scroll till you see the text DrawNode, double click it.

Now you just copy and paste this into the created method

if (e.Node.ImageIndex >= e.Node.TreeView.ImageList.Images.Count) // if there is no image
{
    int imagewidths = e.Node.TreeView.ImageList.ImageSize.Width;
    int textheight = TextRenderer.MeasureText(e.Node.Text, e.Node.NodeFont).Height;
    int x = e.Node.Bounds.Left - 3 - imagewidths / 2;
    int y = (e.Bounds.Top + e.Bounds.Bottom) / 2+1;

    Point point = new Point(x - imagewidths/2, y - textheight/2); // the new location for the text to be drawn

    TextRenderer.DrawText(e.Graphics, e.Node.Text, e.Node.NodeFont, point, e.Node.ForeColor);
}
else // drawn at the default location
    TextRenderer.DrawText(e.Graphics, e.Node.Text, e.Node.TreeView.Font, e.Bounds, e.Node.ForeColor);
Superelevation answered 3/2, 2013 at 2:47 Comment(2)
Does not quite work. Selection is still drawn on it's original location (dislocated to the right relative to nodes without images).Raphaelraphaela
Your answer helped me, but I tidied up the logic. It's just Bounds.Left that you need to manipulate to hide the whitespace.Cancellate
A
0

Hei bro, i found a way. Set the first image as an empty image, like this...

TreeView treeView = new TreeView();
treeView.ImageList.Images.Add(new Bitmap(1,1));

So, the index 0 is an empty image. I hope this helps

Adelladella answered 9/7, 2015 at 19:43 Comment(1)
This method leaves a blank space, contrary to what the original poster asked for.Forerunner
P
0

I ran into this issue and solved it by iterating the nodes that I wanted to have no icon and setting the ImageIndex and SelectedImageIndex properties to values higher than the ImageList AFTER all of the nodes had been already been added to the TreeView. Setting these properties before all of the other nodes were added resulted in only the first one not having the icon.

Piscine answered 16/10, 2023 at 13:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.