C# 用户控件(User Control)详解:创建、使用与最佳实践
在C#应用程序开发中,用户控件(User Control)是一种强大的工具,它允许开发者将多个标准控件组合成一个可复用的自定义组件。无论是Windows Forms还是WPF,用户控件都能显著提高UI开发的效率,减少重复代码,并增强代码的可维护性。
1. 什么是用户控件?
用户控件是一种复合控件,它允许开发者将多个现有的控件(如Button
、TextBox
、Label
等)组合成一个新的、可重用的组件。它继承自UserControl
类,并可以像普通控件一样被拖放到窗体上使用。
用户控件的主要优势
-
代码复用:避免重复编写相同的UI逻辑。
-
封装性:隐藏内部实现细节,仅暴露必要的属性和方法。
-
可维护性:修改用户控件的内部逻辑不会影响使用它的窗体。
-
设计时支持:在Visual Studio的设计器中可以像标准控件一样使用。
2. 创建用户控件
2.1 在Windows Forms中创建用户控件
-
在Visual Studio中创建:
-
右键项目 → 选择 "添加" → "用户控件"。
-
输入名称(如
MyCustomControl
),点击 "添加"。 -
VS会自动生成
.cs
和.Designer.cs
文件。
-
-
基本结构:
public partial class MyCustomControl : UserControl {public MyCustomControl(){InitializeComponent(); // 初始化控件} }
-
添加控件:
-
在设计视图中拖放
Button
、TextBox
等控件。 -
在代码中访问它们:
private void btnSubmit_Click(object sender, EventArgs e) {MessageBox.Show("Button clicked!"); }
-
2.2 在WPF中创建用户控件
WPF的用户控件略有不同,它使用XAML定义UI,并支持数据绑定和依赖属性。
-
创建WPF用户控件:
-
右键项目 → "添加" → "用户控件(WPF)"。
-
默认生成
.xaml
和.xaml.cs
文件。
-
-
XAML定义:
<UserControl x:Class="MyApp.MyWpfControl"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"><StackPanel><TextBlock x:Name="lblTitle" Text="My WPF Control" /><Button x:Name="btnAction" Content="Click Me" Click="btnAction_Click" /></StackPanel> </UserControl>
-
后台代码:
public partial class MyWpfControl : UserControl {public MyWpfControl(){InitializeComponent();}private void btnAction_Click(object sender, RoutedEventArgs e){MessageBox.Show("WPF Button Clicked!");} }
3. 自定义属性和事件
3.1 自定义属性
用户控件可以暴露自定义属性,以便外部代码修改其行为。
Windows Forms 示例
private string _title = "Default Title";[Category("Appearance")] // 在属性窗口中分组
[Description("设置控件的标题")] // 显示描述
public string Title
{get { return _title; }set {_title = value;lblTitle.Text = value; // 更新UI}
}
WPF 示例(依赖属性)
public static readonly DependencyProperty TitleProperty =DependencyProperty.Register("Title", typeof(string), typeof(MyWpfControl),new PropertyMetadata("Default Title", OnTitleChanged));public string Title
{get { return (string)GetValue(TitleProperty); }set { SetValue(TitleProperty, value); }
}private static void OnTitleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{var control = d as MyWpfControl;if (control != null){control.lblTitle.Text = e.NewValue.ToString();}
}
3.2 自定义事件
用户控件可以定义事件,以便外部代码响应内部控件的交互。
Windows Forms 示例
public event EventHandler SubmitClicked;private void btnSubmit_Click(object sender, EventArgs e)
{SubmitClicked?.Invoke(this, EventArgs.Empty);
}
WPF 示例(路由事件)
public static readonly RoutedEvent SubmitClickedEvent =EventManager.RegisterRoutedEvent("SubmitClicked",RoutingStrategy.Bubble,typeof(RoutedEventHandler),typeof(MyWpfControl));public event RoutedEventHandler SubmitClicked
{add { AddHandler(SubmitClickedEvent, value); }remove { RemoveHandler(SubmitClickedEvent, value); }
}private void btnSubmit_Click(object sender, RoutedEventArgs e)
{RaiseEvent(new RoutedEventArgs(SubmitClickedEvent, this));
}
4. 在项目中使用用户控件
4.1 Windows Forms 使用方式
-
拖放方式:
-
编译项目后,用户控件会出现在工具箱。
-
直接拖拽到窗体上即可。
-
-
动态添加:
var myControl = new MyCustomControl(); myControl.Title = "Dynamic Control"; myControl.SubmitClicked += (s, e) => MessageBox.Show("Submitted!"); this.Controls.Add(myControl);
4.2 WPF 使用方式
-
XAML 引用:
<Window xmlns:local="clr-namespace:MyApp"><Grid><local:MyWpfControl Title="Hello WPF!" SubmitClicked="MyWpfControl_SubmitClicked" /></Grid> </Window>
-
动态添加:
var myControl = new MyWpfControl(); myControl.Title = "Dynamic WPF Control"; myControl.SubmitClicked += MyWpfControl_SubmitClicked; myGrid.Children.Add(myControl);
5. 最佳实践
-
封装内部逻辑:避免暴露内部控件的细节,仅提供必要的API。
-
提供设计时支持:使用
[Category]
、[Description]
等特性增强设计器体验。 -
支持数据绑定(WPF):尽量使用
DependencyProperty
而不是普通属性。 -
处理默认样式:在WPF中,可以使用
Style
和Template
增强可定制性。 -
提供充分的文档:注释公共属性和方法,方便团队协作。
6. 常见问题与解决方案
Q1. 用户控件不显示在工具箱?
-
原因:项目未编译或控件未正确生成。
-
解决方案:重新生成项目,或手动从工具箱选择项添加。
Q2. WPF用户控件如何支持MVVM?
-
解决方案:使用
DependencyProperty
和ICommand
实现数据绑定。
Q3. 如何让用户控件自适应布局?
-
Windows Forms:设置
Anchor
或Dock
属性。 -
WPF:使用
Grid
、StackPanel
等布局容器。
结论
C#用户控件是构建可复用UI组件的强大工具,无论是Windows Forms还是WPF,都能显著提升开发效率。通过合理设计自定义属性、事件和封装逻辑,可以创建高度可维护的UI组件。希望本文能帮助你掌握用户控件的核心概念,并在实际项目中灵活运用!
相关文章:

C# 用户控件(User Control)详解:创建、使用与最佳实践
在C#应用程序开发中,用户控件(User Control)是一种强大的工具,它允许开发者将多个标准控件组合成一个可复用的自定义组件。无论是Windows Forms还是WPF,用户控件都能显著提高UI开发的效率,减少重复代码&…...

OpenWrt 搭建 samba 服务器的方法并解决 Windows 不允许访问匿名服务器(0x80004005的错误)的方法
文章目录 一、安装所需要的软件二、配置自动挂载三、配置 Samba 服务器四、配置 Samba 访问用户和密码(可选)新建 Samba 专门的用户添加无密码的 Samba 账户使用root账户 五、解决 Windows 无法匿名访问Samba方案一 配置无密码的Samba账户并启用匿名访问…...

【 Redis | 完结篇 缓存优化 】
前言:本节包含常见redis缓存问题,包含缓存一致性问题,缓存雪崩,缓存穿透,缓存击穿问题及其解决方案 1. 缓存一致性 我们先看下目前企业用的最多的缓存模型。缓存的通用模型有三种: 缓存模型解释Cache Asi…...

AI数据集构建:从爬虫到标注的全流程指南
AI数据集构建:从爬虫到标注的全流程指南 系统化学习人工智能网站(收藏):https://www.captainbed.cn/flu 文章目录 AI数据集构建:从爬虫到标注的全流程指南摘要引言流程图:数据集构建全生命周期一、数据采…...
Android 颜色百分比对照
本文就是简单写个demo,打印下颜色百分比的数值.方便以后使用. 1: 获取透明色 具体的代码如下: /*** 获取透明色* param percent* param red* param green* param blue* return*/public static int getTransparentColor(int percent, int red, int green, int blue) {int alp…...

AI破局:饿了么如何搅动即时零售江湖
最近,即时零售赛道打的火热,对我们的生活也产生了不少的影响。 美女同事小张就没少吐槽“他们咋样了我不知道,奶茶那么便宜,胖了五六斤不说,钱包也空了,在淘宝买奶茶的时候,换了个手机还买了不少…...

04 APP 自动化- Appium toast 元素定位列表滑动
文章目录 一、toast 元素的定位二、滑屏操作 一、toast 元素的定位 toast 元素就是简易的消息提示框,toast 显示窗口显示的时间有限,一般3秒左右 # -*- codingutf-8 -*- from time import sleep from appium import webdriver from appium.options.an…...
判断它是否引用了外部库
在一个 C# 项目中,要系统性地判断它是否引用了外部库(包括 NuGet 包、引用的 DLL、项目间依赖等),你应从以下几个关键维度入手进行检查和分析: 1. 检查 .csproj 项目文件 C# 项目使用 .csproj 文件(MSBuil…...

物流项目第十期(轨迹微服务)
本项目专栏: 物流项目_Auc23的博客-CSDN博客 建议先看这期: MongoDB入门之Java的使用-CSDN博客 物流项目第九期(MongoDB的应用之作业范围)-CSDN博客 业务需求 快递员取件成功后,需要将订单转成运单,用…...
Python 入门到进阶全指南:从语言特性到实战项目
一、Python 简介 Python 是一种高级、跨平台、解释型编程语言,以简洁语法和高可读性著称,既适合编程初学者快速入门,也能满足资深开发者的复杂需求。其核心特性与应用场景如下: 核心特性解析 解释型语言:无需编译即可…...

【数据库】关系数据理论--规范化
1.问题的提出 关系模式由五部分组成,是一个五元组: R(U, D, DOM, F) (1)关系名R是符号化的元组语义 (2)U为一组属性 (3)D为属性组U中的属性所来自的域 (4)DOM…...
SQL 中 JOIN 的执行顺序优化指南
SQL 中 JOIN 的执行顺序优化指南 一、JOIN 执行顺序基础原理 在 SQL 查询中,JOIN的执行顺序是查询优化的重要环节。数据库引擎会根据多种因素决定最优的 JOIN 顺序: 逻辑执行顺序:SQL 语句的书写顺序(如 FROM → WHERE → GROUP BY)并不代表实际执行顺序物理执行顺序:由查…...

Oracle双平面适用场景讨论会议
4月28日,我在杭州组织召开了Oracle双平面会议讨论沙龙。在国产化数据库浪潮的今天,Oracle数据库作为国产数据库的应急库,在国产数据库发生故障或者性能下降时,如何更好的使用Oracle。会议主题如下: 1、背景与痛点速览&…...
OD 算法题 B卷【矩阵稀疏扫描】
文章目录 矩阵稀疏扫描 矩阵稀疏扫描 如果矩阵中的很多系数都为零,则为稀疏矩阵,给定一个矩阵,如果某行、列存在0的个数超出(包含)了行宽、列宽的一半(整除),则认为该行、列为稀疏的…...

使用BERT/BiLSTM + CRF 模型进行NER进展记录~
使用代码处理数据集,发现了一些问题,以及解决办法~ 下载了一组数据集,数据存放在CSV中,GBK格式。如下: 首先对每一列直接进行NER抽取,结果非常不好: 几乎是乱抽取的,解决办法是自己创…...
HarmonyOS运动开发:精准估算室内运动的距离、速度与步幅
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在室内运动场景中,由于缺乏 GPS 信号,传统的基于卫星定位的运动数据追踪方法无法使用。因此,如何准确估算室内运动的距离、速度和步幅,…...

Web攻防-SQL注入高权限判定跨库查询文件读写DNS带外SecurePriv开关绕过
知识点: 1、Web攻防-SQL注入-高权限用户差异 2、Web攻防-SQL注入-跨库注入&文件读写&DNS带外 案例说明: 在应用中,数据库用户不同,可操作的数据库和文件读写权限不一,所有在注入过程中可以有更多的利用思路&a…...

C语言数据结构笔记3:Union联合体+结构体取8位Bool量
本文衔接上文要求,新增8位bool量的获取方式。 目录 问题提出: Union联合体struct结构体(方式1): Union联合体struct结构体(方式2): BYTE方式读取: 问题提出: 在STM32单片机的编程中,无法定义Boo…...
深拷贝与浅拷贝的区别?如何手写实现一个深拷贝?
导语: “深拷贝 VS 浅拷贝”是前端面试中绕不开的经典问题,既能考察 JavaScript 基础功,又能延伸至手写代码、递归、循环引用处理等进阶话题。本文从面试官视角解析其考察重点,并详解如何手写一个实用的深拷贝函数,助你…...
grafana 批量视图备份及恢复(含数据源)
一、grafana 批量视图备份 import requests import json import urllib3 import osfrom requests.auth import HTTPBasicAuthfilename_folders_map "folders_map.json" type_folder "dash-folder" type_dashboard "dash-db"# Grafana服务器地…...

SAP学习笔记 - 开发22 - 前端Fiori开发 数据绑定(Jason),Data Types(数据类型)
上一章讲了Icons(图标),Icon Explorer。 SAP学习笔记 - 开发21 - 前端Fiori开发 Icons(图标),Icon Explorer(图标浏览器)-CSDN博客 本章继续讲SAP Fiori开发的知识。 目录 1&…...

网络编程之TCP编程
基于 C/S :客户端(client)/服务器端(server) 1.流程 2. 函数接口 所有函数所需头文件: #include <sys/types.h> #include <sys/socket.h> 系统定义好了用来存储网络信息的结构体 ipv4通信使…...

C++进阶--C++11(04)
文章目录 C进阶--C11(04)lambdalambda表达式语法捕捉列表lambda的应用lambda的原理 包装器functionbind 总结结语 很高兴和大家见面,给生活加点impetus!!开启今天的编程之路!! 今天我们进一步c…...

当AI遇上防火墙:新一代智能安全解决方案全景解析
在2025年网络安全攻防升级的背景下,AI与防火墙的融合正重塑安全防御体系。以下三款产品通过机器学习、行为分析等技术创新,为企业提供智能化主动防护: 1. 保旺达数据安全管控平台——AI驱动的动态治理引擎 智能分类分级:基于…...
STL 库基础概念与示例
一、STL 库基础概念与示例 1. 容器分类 顺序容器 核心特性:按元素插入顺序存储,支持下标访问(类似数组),动态扩展内存。典型容器:vector(动态数组)。适用场景:需要频繁…...

Spring MVC参数绑定终极手册:单多参/对象/集合/JSON/文件上传精讲
我们通过浏览器访问不同的路径,就是在发送不同的请求,在发送请求时,可能会带一些参数,本文将介绍了Spring MVC中处理不同请求参数的多种方式 一、传递单个参数 接收单个参数,在Spring MVC中直接用方法中的参数就可以&…...

Fluence推出“Pointless计划”:五种方式参与RWA算力资产新时代
2025年6月1日,去中心化算力平台 Fluence 正式宣布启动“Pointless 计划”——这是其《Fluence Vision 2026》战略中四项核心举措之一,旨在通过贡献驱动的积分体系,激励更广泛的社区参与,为用户带来现实世界资产(RWA&am…...

innovus: ecoAddRepeater改变hier层级解决办法
我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧? 拾陆楼知识星球入口 来自星球提问: 星主,我在A/B/C/D/E/U0这个cell后面插入一个BUFF,生成的名字为A/B/C/BUFF1,少了D/E两个层级,不应该是生成A/B/C/…...

华为OD机试真题——硬件产品销售方案(2025A卷:100分)Java/python/JavaScript/C++/C语言/GO六种最佳实现
2025 A卷 100分 题型 本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析; 并提供Java、python、JavaScript、C++、C语言、GO六种语言的最佳实现方式! 2025华为OD真题目录+全流程解析/备考攻略/经验分享 华为OD机试真题《硬件产品销售方案》: 目录…...
突破数据孤岛:StarRocks联邦查询实战指南
随着企业数据生态的复杂化,跨多个数据存储系统进行联合查询的需求日益增长。本文将深入解析如何利用StarRocks构建高效的数据联邦查询体系,实现与Apache Doris和Hive数据仓库的无缝对接。 ### 一、StarRocks联邦查询架构解析 StarRocks采用分布式架构设…...