惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Blog — PlanetScale
Blog — PlanetScale
J
Java Code Geeks
N
Netflix TechBlog - Medium
Martin Fowler
Martin Fowler
A
About on SuperTechFans
腾讯CDC
B
Blog RSS Feed
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Microsoft Azure Blog
Microsoft Azure Blog
D
Docker
Y
Y Combinator Blog
Microsoft Security Blog
Microsoft Security Blog
F
Fortinet All Blogs
I
InfoQ
博客园 - 【当耐特】
美团技术团队
GbyAI
GbyAI
量子位
宝玉的分享
宝玉的分享
爱范儿
爱范儿
有赞技术团队
有赞技术团队
博客园 - Franky
L
LangChain Blog
阮一峰的网络日志
阮一峰的网络日志

博客园 - 老码识途呀

基于.NET的Windows窗体编程之WinForms滑块与上下控件 基于.NET的Windows窗体编程之WinForms文件监控 基于.NET的Windows窗体编程之WinForms音频控件 基于.NET的Windows窗体编程之WinForms图像控件 基于.NET的Windows窗体编程之WinForms提示控件 基于.NET的Windows窗体编程之WinForms时间控件 基于.NET的Windows窗体编程之WinForms图表控件 基于.NET的Windows窗体编程之WinForms输入与显示 基于.NET的Windows窗体编程之WinForms菜单工具栏 基于.NET的Windows窗体编程之WinForms打印 基于.NET的Windows窗体编程之WinForms对话框 基于.NET的Windows窗体编程之WinForms列表控件 基于.NET的Windows窗体编程之WinForms数据表格 基于.NET的Windows窗体编程之WinForms事件简介 基于.NET的Windows窗体编程之WinForms布局简介 基于.NET的Windows窗体编程之WinForms控件简介 基于.NET的Windows窗体编程之WinForms入门简介 推荐一款基于.NET和百度飞桨的OCR识别组件 新书速递,手把手教你WPF入门与开发 推荐一种并发线程中资源同步常用方法 推荐一种手动设置异步线程等待机制的解决方案 推荐一种异步线程执行过程中更新进度的方法 推荐一款基于.NET的进程间数据交互经典解决方案 推荐一款线程or进程间数据同步解决方案 推荐一款代码规范检查(CodeReview)神器 推荐一款高性能状态机管理解决方案 推荐一款进程间高速交换数据的解决方案 推荐一款基于.NET的进程间通信框架 推荐一款基于EF-Core的分库分表利器 推荐一种程序崩溃闪退或卡死的分析方法
基于.NET的Windows窗体编程之WinForms自定义控件(1)
老码识途呀 · 2026-09-14 · via 博客园 - 老码识途呀

在实际应用开发中,可能UI框架的默认控件,已经不能满足实际的应用需求,或者某些功能被大量的重复应用,如果每一个使用的地方都书写大量的重复代码,则不仅会浪费精力,且让维护变得复杂,此时就需要将包含特定功能的部分封装成控件,便于重复使用。自定义控件就像造轮子,轮子造好以后,别的地方可以一键复用。今天我们以一些简单的小例子,简述基于.NET的Windows窗体编程中自定义控件的相关应用,仅供学习分享使用,如有不足之处,还请指正。

image

概述

一般而言,自定义控件,是在Visual Studio提供的默认控件不能满足实际的工作需要,才需要在现有控件的基础之上进行新的扩展,来实现自己的功能。自定义控件有自己特有的属性,事件,方法来支撑特定的功能。自定义控件封装实现的细节,可以进行方便的复用。自定义控件主要有以下三种分类,本例采用的是第三种。

  1. 用户控件(User Control),又称之为复合控件(Composite Controls),将现有的各种控件组合起来,形成一个新的控件,来满足用户的需求。复合控件的设计方式与窗体类似,具有可视化设计器。 通过视觉设计器创建、排列和修改构成控件。 控件事件和逻辑的编写方式与设计窗体时完全相同。 用户控件与其他任何控件一样放置在表单上。
  2. 扩展控件(Extended Controls):就是在现有的控件基础上,派生出一个新的控件,增加新的功能,或者修改原有功能,来满足用户需求。
  3. 自定义控件(Custom Controls):就是直接从UserControl类派生,也就是说完全由自己来设计、实现一个全新的控件,这是最灵活、最强大的方法。

今天主要讲解用户控件,至于扩展控件和自定义控件,在后续篇幅继续讲解。

用户控件

用户控件是封装在通用容器中的 Windows 窗体控件的集合。 此类控件称为 复合控件。 其包含的控件称为构成控件。 复合控件派生自 UserControl 类。自定义的复合控件可以在创建它们的项目中使用,也可以在引用这些用户控件库的其他项目中使用。用户控件的代码实现模式是:

  • 事件转发 - 将事件从内部控件传递到使用者。
  • 属性公开 - 允许使用者访问内部控制属性。
  • 逻辑行为 - 处理内部控件之间的交互。

创建用户控件

由于用户控件可以在创建它的项目中使用,也可也可以在引用这些用户控件库的其他项目中使用,所以为了将用户控件单独存放,我们创建一个独立的用户控件库,并命名为“Okcoder.WinForm.UserControls”。选择控件库,然后点击右键,在弹出的快捷菜单中,选择“添加”,然后选择“用户控件(Windows窗体)(U)...”如下图所示:

image

在弹出的“添加新项”对话框中,选择“用户控件(Windows窗体)”,然后输入名称,点击“添加”按钮即可,如下图所示:

image

在本示例中,用户控件名称为“ClearableTextBox”,主要功能为设计一个可清除文本框。首先设计用户空间的页面,它包括如下几部分:

  1. 一个Label,用于显示用户控件的标题,命名为“lblTitle”
  2. 一个文本框,用于用户输入内容,命名为“txtValue”
  3. 一个按钮,用于点击按钮,清除文本框的内容,命名为“btnClear”

布局后页面,如下所示:

image

公开属性,打开用户控件的后台代码页面,添加两个属性,主要用于:

  1. 公开Title属性,可以让应用控件的地方获取或设置控件的标题,并将Title属性和显示在lblTitle上。
  2. 公开Text属性,可以让应用控件的地方获取和设置控件的文本框内容,并将Text属性和txtValue相关联。

具体公开属性如下所示:

[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public string Title
{
	get => lblTitle.Text;
	set => lblTitle.Text = value;
}

[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public new string Text
{
	get => txtValue.Text;
	set => txtValue.Text = value;
}

事件转发,增加TextChanged事件,并将此事件注册到文本框的TextChanged事件中,当应用用户的控件程序注册TextChanged事件时,就可以响应文本框的文本变化。如下所示:

[Browsable(true)]
public new event EventHandler? TextChanged
{
	add => txtValue.TextChanged += value;
	remove => txtValue.TextChanged -= value;
}

封装逻辑行为,封装清除按钮的逻辑,为btnClear按钮增加Click事件的处理逻辑,如下所示:

private void btnClear_Click(object sender, EventArgs e)
{
    Text = "";
}

应用用户控件

用户控件创建完成,且项目编译成功后,在需要应用用户控件的项目引用控件库“Okcoder.WinForm.UserControls”,就可以在工具箱中,看到创建的自定义控件,然后拖动控件到Form表单中,如下所示:

image

分别设置拖动到页面的两个用户控件的标题为First Name,Last Name,然后注册两个控件的TextChanged事件,如下所示:

image

在Form表单的后台代码中,为用户控件的TextChanged事件添加处理逻辑,当用户内容发生变化时,将内容显示在名称为“lblFullName”的Lable上,如下所示:

namespace Okcoder.WinForm.Demo
{
    public partial class FrmUserControls : Form
    {
        public FrmUserControls()
        {
            InitializeComponent();
        }

        private void UpdateNameLabel()
        {
            if (string.IsNullOrWhiteSpace(ctlFirstName.Text) || string.IsNullOrWhiteSpace(ctlLastName.Text))
                lblFullName.Text = "Please fill out both the first name and the last name.";
            else
                lblFullName.Text = $"Hello {ctlFirstName.Text} {ctlLastName.Text}, I hope you're having a good day.";
        }

        private void ctlFirstName_TextChanged(object sender, EventArgs e)
        {
            UpdateNameLabel();
        }

        private void ctlLastName_TextChanged(object sender, EventArgs e)
        {
            UpdateNameLabel();
        }

        private void FrmUserControls_Load(object sender, EventArgs e)
        {
            UpdateNameLabel();
        }
    }
}

运行实例

运行实例,效果如下所示:

image

以上就是《基于.NET的Windows窗体编程之WinForms自定义控件(1)》的全部内容,旨在抛砖引玉,一起学习,共同进步!!!