【问题标题】:Cannot set icon for node of treeview无法设置树视图节点的图标
【发布时间】:2012-07-16 08:53:11
【问题描述】:

我有一个包含 1 个图标 (folder.ico) 的树视图和一个 imageList,我只想为根节点设置图标,子节点没有图标,所以我尝试为子节点设置图像索引但是有问题,看图:

我的代码:

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

谢谢

编辑 我在@Killercam 的回答下创建了一个自定义 TreeView:

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

然后在我的代码中使用它:

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

    }
}

结果还是不行,文字前还有一个文件夹图标!

【问题讨论】:

标签: c# winforms


【解决方案1】:

你不能做你需要的事

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

不覆盖控件。我还发现您无法使用标准 WinForms TreeView 为不同的节点显示不同的图像。下面是一些使 TreeView 看起来更好的代码;这将为子节点绘制树线的一小部分。

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

这将为您提供如下所示的 TreeView:

这里我的主节点 (Node[0]) 是没有指定 Image 的节点,它是您的 File1/File2 节点所需要的。

我希望这会有所帮助。

【讨论】:

  • 看起来这将有助于解决我的问题。我会尽快尝试并反馈。
  • 还有一个问题,这个自定义控件怎么用?
  • 将代码复制到相关的命名空间中。编译代码,你会看到一个新的CustomTreeView控件出现在VS2010右侧的ToolBox中。它将在_YourApp_ Componants 下。拖放这个 ike 你会从工具箱中做一个普通的TreeView 控件...
  • OnDrawNode 方法似乎不能正常工作,它总是在默认的 hmm 处绘制节点。你能再次检查你的代码吗?我尝试了,但它不起作用:(
  • @HanTran 此事件构成现有代码的活动部分。它按原样工作。像以前的控制一样使用它。你是什​​么意思它不起作用?发生了什么?
【解决方案2】:

目前您创建的图片列表只有一张图片(索引为 0)

treeView1.ImageList = imageList; 行将列表链接到树视图

node2.ImageIndex = 100; 行链接要显示的列表中索引 100(不存在)处的图像

您在列表中只有一张图片,这意味着您只有在索引 0 处有一张图片。

那就试试吧:

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

【讨论】:

  • 我设置为 100 意味着我不会为子节点设置任何图标。我想要的只是不在子节点上显示图标。
  • treeview 将设置默认图标 (folder.ico)
【解决方案3】:

尝试使用空白图像文件?

(或者只包含水平点画线,或者箭头...)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-12
    • 2010-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多