在 C# 中创建自定义控件是扩展 WinForms 或 WPF 功能的重要方式。以下是创建自定义控件的详细指南:
一、创建自定义控件的两种主要方式
-
用户控件 (UserControl)
- 组合现有控件
- 适合创建复合控件
- 使用 Visual Studio 设计器
-
自定义控件 (继承 Control)
- 完全从头绘制
- 需要重写
OnPaint方法 - 更灵活但更复杂
二、创建 WinForms 自定义控件示例(继承 Control)
using System;
using System.Drawing;
using System.Windows.Forms;
[ToolboxBitmap(typeof(Button))] // 工具箱图标
public class GradientButton : Control
{
// 自定义属性
private Color _gradientStart = Color.LightBlue;
private Color _gradientEnd = Color.DarkBlue;
[Category("Appearance"), Description("渐变起始颜色")]
public Color GradientStart
{
get => _gradientStart;
set { _gradientStart = value; Invalidate(); }
}
[Category("Appearance"), Description("渐变结束颜色")]
public Color GradientEnd
{
get => _gradientEnd;
set { _gradientEnd = value; Invalidate(); }
}
// 构造函数
public GradientButton()
{
SetStyle(ControlStyles.ResizeRedraw |
ControlStyles.OptimizedDoubleBuffer, true);
Size = new Size(100, 40);
}
// 绘制控件
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
using (var brush = new System.Drawing.Drawing2D.LinearGradientBrush(
ClientRectangle, _gradientStart, _gradientEnd, 45f))
{
e.Graphics.FillRectangle(brush, ClientRectangle);
}
using (var pen = new Pen(Color.Black, 1))
{
e.Graphics.DrawRectangle(pen, 0, 0, Width - 1, Height - 1);
}
TextFormatFlags flags = TextFormatFlags.HorizontalCenter |
TextFormatFlags.VerticalCenter;
TextRenderer.DrawText(e.Graphics, Text, Font, ClientRectangle, ForeColor, flags);
}
// 点击效果
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
Color temp = _gradientStart;
_gradientStart = _gradientEnd;
_gradientEnd = temp;
Invalidate();
}
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
Color temp = _gradientStart;
_gradientStart = _gradientEnd;
_gradientEnd = temp;
Invalidate();
}
}
三、关键步骤详解
-
继承基类
public class MyCustomControl : Control { ... } -
添加自定义属性
- 使用
Category和Description特性增强设计时支持 - 在属性变更时调用
Invalidate()重绘
- 使用
-
启用双缓冲 (减少闪烁)
SetStyle(ControlStyles.OptimizedDoubleBuffer, true); -
重写 OnPaint 方法
- 使用
System.Drawing命名空间进行绘制 - 通过
e.Graphics访问绘图表面
- 使用
-
处理交互事件
- 重写
OnMouseDown,OnMouseMove等方法 - 调用
Invalidate()触发重绘
- 重写
四、在项目中使用自定义控件
- 编译项目:生成包含控件的 DLL
- 添加到工具箱:
- 右键工具箱 → 选择项 → 浏览 DLL
- 在窗体上使用:
- 拖放控件到窗体
- 通过属性窗口调整自定义属性
五、高级技巧
-
设计时支持
[Designer("System.Windows.Forms.Design.ControlDesigner, System.Design")] public class MyControl : Control { ... } -
自定义事件
public event EventHandler<MyEventArgs> CustomEvent; protected virtual void OnCustomEvent(MyEventArgs e) { CustomEvent?.Invoke(this, e); } -
UI 状态管理
private ButtonState _state = ButtonState.Normal; protected override void OnMouseEnter(EventArgs e) { _state = ButtonState.Hover; Invalidate(); }
六、WPF 自定义控件要点
- 使用 CustomControl 类
- 创建 Generic.xaml 资源字典
<Style TargetType="{x:Type local:MyCustomControl}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:MyCustomControl}"> <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> <ContentPresenter/> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> - 添加依赖属性
public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(MyCustomControl), new PropertyMetadata(new CornerRadius(0))); public CornerRadius CornerRadius { get => (CornerRadius)GetValue(CornerRadiusProperty); set => SetValue(CornerRadiusProperty, value); }
七、最佳实践
- 命名规范:使用明确的控件后缀(如 Button、Panel)
- 资源释放:实现 IDisposable 释放 GDI 资源
- DPI 适配:使用
Control.Scale()确保高DPI兼容性 - 文档注释:为公共成员添加 XML 注释
- 单元测试:创建测试项目验证控件行为
八、调试技巧
- 设计时调试:附加到另一个 Visual Studio 实例
- 绘制辅助线:临时添加调试绘图代码
- 重写ToString():返回控件状态信息
public override string ToString() => $"{Name} [State: {_state}, Text: {Text}]";
通过以上步骤,您可以创建功能丰富、外观专业的自定义控件。实际开发中建议:
- 从简单控件开始逐步扩展功能
- 参考 .NET 源码学习标准控件实现
- 使用 NuGet 包分发控件库
C#自定义控件创建指南
2029

被折叠的 条评论
为什么被折叠?



