C#重写treeView控件

1.先准备两张图片downdrop.png、downdrop_open.png放在项目Resources里

2.新建用户控件BaseTreeView控件

3.重写控件继承TreeView,记得删除AutoScaleMode这一行,否则会报错

复制代码
public partial class BaseTreeView : TreeView
{
    //这个属性貌似不起作用,还是得配置BackColor不知道是咋回事
    private Color nodeNormalBackColor = Color.FromArgb(10, 52, 112);
    public Color NodeNormalBackColor
    {
        get
        {
            return nodeNormalBackColor;
        }
        set
        {
            nodeNormalBackColor = value;
        }
    }

    private Color nodeSelectBackColor = Color.FromArgb(15, 92, 164);
    public Color NodeSelectBackColor
    {
        get
        {
            return nodeSelectBackColor;
        }
        set
        {
            nodeSelectBackColor = value;
        }
    }

    private Color nodeHoverBackColor = Color.FromArgb(103, 161, 207);
    public Color NodeHoverBackColor
    {
        get
        {
            return nodeHoverBackColor;
        }
        set
        {
            nodeHoverBackColor = value;
        }
    }

    private Color nodeTestColor = Color.FromArgb(203, 239, 255);

    public Color NodeTestColor
    {
        get
        {
            return nodeTestColor;
        }
        set
        {
            nodeTestColor = value;
        }
    }

    public BaseTreeView()
    {
        InitializeComponent();

        this.DrawMode = TreeViewDrawMode.OwnerDrawAll;
        this.FullRowSelect = true;
        this.ItemHeight = 46;
        this.HotTracking = true;
        this.ShowLines = true;
    }

    protected override void OnDrawNode(DrawTreeNodeEventArgs e)
    {
        base.OnDrawNode(e);

        //节点背景绘制
        if (e.Node.IsSelected)
        {
            //e.Graphics.DrawImage(Properties.Resources.tree_bg, e.Bounds);
            e.Graphics.FillRectangle(new SolidBrush(nodeSelectBackColor), e.Bounds);
        }
        else if ((e.State & TreeNodeStates.Hot) != 0)//|| currentMouseMoveNode == e.Node)
        {
            //e.Graphics.DrawImage(Properties.Resources.tree_bg, e.Bounds);
            e.Graphics.FillRectangle(new SolidBrush(nodeHoverBackColor), e.Bounds);
        }
        else if (e.Node.BackColor != null) {
            //这个是用于特殊单独需要在代码里设置结点背景颜色时使用
            Color color = e.Node.BackColor; // 获取背景色的全部分量
            e.Graphics.FillRectangle(new SolidBrush(color), e.Bounds);
        }
        else{
            e.Graphics.FillRectangle(new SolidBrush(nodeNormalBackColor), e.Bounds);
        }

        //节点头图标绘制
        if (e.Node.IsExpanded)
        {
            e.Graphics.DrawImage(Resources.downdrop_open, e.Node.Bounds.X - 18, e.Node.Bounds.Y + 10);
        }
        else if (e.Node.IsExpanded == false && e.Node.Nodes.Count > 0)
        {
            e.Graphics.DrawImage(Resources.downdrop, e.Node.Bounds.X - 18, e.Node.Bounds.Y + 10);
        }

        //文本绘制
        using (Font foreFont = new Font(this.Font, FontStyle.Regular))
        using (Brush drawTextBrush = new SolidBrush(nodeTestColor))
        {
            e.Graphics.DrawString(e.Node.Text, foreFont, drawTextBrush, e.Node.Bounds.Left + 15, e.Node.Bounds.Top + 5);
        }
    }

    protected override void OnMouseClick(MouseEventArgs e)
    {
        base.OnMouseClick(e);
        TreeNode tn = this.GetNodeAt(e.Location);
        this.SelectedNode = tn;
    }

    TreeNode currentNode = null;
    protected override void OnMouseMove(MouseEventArgs e)
    {
        base.OnMouseMove(e);
        TreeNode tn = this.GetNodeAt(e.Location);
        Graphics g = this.CreateGraphics();
        if (currentNode != tn)
        {
            //绘制当前节点的hover背景
            if (tn != null)
                OnDrawNode(new DrawTreeNodeEventArgs(g, tn, new Rectangle(0, tn.Bounds.Y, this.Width, tn.Bounds.Height), TreeNodeStates.Hot));

            //取消之前hover的节点背景
            if (currentNode != null)
                OnDrawNode(new DrawTreeNodeEventArgs(g, currentNode, new Rectangle(0, currentNode.Bounds.Y, this.Width, currentNode.Bounds.Height), TreeNodeStates.Default));
        }
        currentNode = tn;
        g.Dispose();
    }


    protected override void OnMouseLeave(EventArgs e)
    {
        base.OnMouseLeave(e);
        //移出控件时取消Hover背景
        if (currentNode != null)
        {
            Graphics g = this.CreateGraphics();
            OnDrawNode(new DrawTreeNodeEventArgs(g, currentNode, new Rectangle(0, currentNode.Bounds.Y, this.Width, currentNode.Bounds.Height), TreeNodeStates.Default));
        }
    }

    /// <summary>
    /// 防止treeNode闪屏
    /// </summary>
    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams cp = base.CreateParams;
            if (!DesignMode)
            {
                cp.ExStyle |= 0x02000000;// Turn on WS_EX_COMPOSITED 
            }
            return cp;

        }
    }
}

4.重新生成程序,在工具箱中就会出现BaseTreeView控件,拉到界面中即可使用

5.在使用界面中为TreeView添加几个数据测试

复制代码
//创建父节点
TreeNode treeNode = baseTreeView1.Nodes.Add("组织结构");

//创建子节点
TreeNode treeNode_1 = new TreeNode("C");
TreeNode treeNode_2 = new TreeNode("C++");
TreeNode treeNode_3 = new TreeNode("C#");

//给父节点添加子节点
treeNode.Nodes.Add(treeNode_1);
treeNode.Nodes.Add(treeNode_2);
treeNode.Nodes.Add(treeNode_3);

将文字设置大一点,背景颜色设置的深一点更好看

相关推荐
MayBaymax1 小时前
Spring AI Alibaba Graph 实战:客服工单智能处理
java·ai·ai编程
光依旧2 小时前
MCP实战手记系列(五):让工具返回一个能点的界面(文末附github源码链接)
java·spring ai·前端集成·mcp·mcp apps
Lost of 程序猿2 小时前
用 YARP 为 .NET 微服务搭一座“立交桥“:路由转发与生产配置实践
c#·asp.net
APIshop2 小时前
淘宝选品接口实战:从召回、详情、佣金到转链的 Java 接入笔记
java
泡茶喝茶写代码2 小时前
量化数据进阶:多维实战篇(第 11 篇):历史涨跌停价:涨跌停序列与止损线测算
java·python·股票数据api·股票数据·股票数据api接口·股票api数据接口·股票量化数据api
景熙55232 小时前
单体项目编写思路和落地形式
java·开发语言
Ivanqhz2 小时前
Slope One 算法详解:与矩阵分解、共现矩阵的异同
java·服务器·网络·人工智能·深度学习
Bs_MoneyMagnet3 小时前
基于springboot+vue的非遗物质文化遗产系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·spring·毕业设计·计算机毕业设计
万物智能3 小时前
波形发生AD9833模块配置—【万物智能之开源鸿蒙OpenHarmony系统实战开发系列教程】
java
计算机毕设定制辅导-无忧学长3 小时前
《基于SpringBoot的未成年人健康知识科普平台的设计与实现》
java·开发语言·vue.js·spring boot·未成年人健康知识科普平台