对标 HandyControl 的开源免费 WPF 控件库 — 高颜值、功能齐全、支持工业场景

前言

在 WPF 开发中界面美观与交互体验早已不再是”锦上添花”,而是项目成败的关键因素之一。不过,原生 WPF 控件虽然稳定可靠,但在视觉表现力和现代化交互设计上略显朴素,我们常常需要花费大量时间重写样式、封装逻辑,甚至从零造轮子。

本文推荐一套开箱即用、风格统一、功能丰富的自定义控件库,该库参考 HandyControl和ElementUI的设计理念,能让我们把精力真正聚焦在业务逻辑上。

项目介绍

一套对标 HandyControl 和 Element UI 的现代化 WPF 控件库。它不仅继承了 WPF 强劲的数据绑定与模板机制,更融入了当代 UI/UX 设计理念,为 .NET 桌面应用注入了新的活力。

项目的目标很明确:打造一套轻量、易用、高颜值、功能完整的 WPF 控件集合,协助大家快速开发专业级桌面应用,尤其适合内部工具、工业软件、数据看板等对交互与视觉有较高要求的场景。

项目功能

控件库覆盖了桌面应用所需的绝大多数 UI 元素。它不仅包含基础控件的增强版(如带标题提示的 TextBox、密码框、搜索框),还提供了大量原生 WPF 缺失的高级组件:

1、布局与容器类

SwitchTabControl(可切换样式的标签页)、UTabControl(动态菜单 Tab)、GroupBox 多种美化样式;

2、输入与选择类

SearchTextBox(智能搜索框)、InputNumber(数字输入)、CascaderSelector(级联选择器)、CalendarView(日历控件);

3、反馈与状态类

UDialog(模态弹窗)、UDrawer(抽屉侧边栏)、MessageHost(消息提示宿主)、Notify 提示框;

4、数据展示类

TimelineControl(时间线)、StepBar(步骤条)、Pagination(分页器)、Badge(徽标标记);

5、加载与进度类

CircularProgressBar(环形进度条)、ProgressLoading、RingLoading、DotLoading 等多种加载动画;

6、特色交互控件

RadialToolbar(径向工具圆盘)、CompareSpliter(图片对比滑块)、FloatingBlock(浮动提示块)、BreathLamp(呼吸灯效果);

7、行业专用组件

Meter(仪表盘)、BatteryControl(电池电量)、RaderChart(雷达图)、Fan(风扇动效)、Pipeline(管道流动)等可视化控件。

项目说明

控件并非简单堆砌,而是经过精心设计与统一风格打磨。

例如,所有按钮都支持 3D 风格、信息/成功/警告/错误等语义化样式;

输入框通过附加属性(如 TitleAttachHelper)轻松实现带标签、占位符、必填标识的复合输入区域;

而像”氛围+呼吸灯”这类控件,则巧妙结合了动画与数据绑定,适用于监控、IoT 等场景。

项目技术

技术实现上,项目充分利用 WPF 的核心优势。

控件大量使用 DependencyPropertyControlTemplateStyle进行解耦,支持通过 XAML 直接配置外观与行为。

同时,广泛采用 MVVM 模式,配合 RelativeSource绑定、自定义附加属性(如IconAttachHelperPasswordAttachHelper)等技巧,极大提升开发效率和代码可维护性。

底层动画则依托 WPF 的 StoryboardDoubleAnimation,流畅自然,资源占用低。

项目代码

管道绘制

private void DrawPipe(DrawingContext drawingContext, double Radius,double len1,double len2)
{
// 径向发散
RadialGradientBrush radBrush = new RadialGradientBrush;
radBrush.GradientOrigin = new Point(0.5, 0.5);
radBrush.GradientStops.Add(new GradientStop(Colors.Gray, 0));
radBrush.GradientStops.Add(new GradientStop(Colors.White, 0.5));
radBrush.GradientStops.Add(new GradientStop(Colors.Gray, 1));

// 线性发散
LinearGradientBrush linearBrush = new LinearGradientBrush;
linearBrush.GradientStops.Add(new GradientStop(Colors.Gray, 0));
linearBrush.GradientStops.Add(new GradientStop(Colors.White, 0.5));
linearBrush.GradientStops.Add(new GradientStop(Colors.Gray, 1));

// 路径图形
PathFigure pathFigure = new PathFigure;

if (Direction == "Horizontal")
{
linearBrush.StartPoint = new Point(0, 0);
linearBrush.EndPoint = new Point(0, 1);
// 两个端点都是水平的
if(string.IsNullOrEmpty(BeginDir) && string.IsNullOrEmpty(EndDir))
{
drawingContext.DrawRectangle(linearBrush, null, new Rect(0, 0, len1, Radius));

Point p0 = new Point(0, Radius / 2);
Point p1 = new Point(len1, Radius / 2);
pathFigure.StartPoint = p0;
LineSegment lineSegment = new LineSegment(p1, true);
pathFigure.Segments.Add(lineSegment);
}
// 起点水平,结束端点带方向
elseif (string.IsNullOrEmpty(BeginDir))
{
}
// 起点带方向,结束端点水平
elseif (string.IsNullOrEmpty(EndDir))
{
}
else
{
// 蚂蚁线坐标点
Point p0;
Point p1;
Point p2;
Point p3;
Point p4;
Point p5;

// 绘制一区弧形
if (BeginDir == "Top")
{
EllipseGeometry eGeometry = new EllipseGeometry(new Point(Radius, 0), Radius, Radius);
RectangleGeometry rGeometry = new RectangleGeometry(new Rect(x: 0, 0, Radius, Radius));
CombinedGeometry comb = new CombinedGeometry(eGeometry, rGeometry);
comb.GeometryCombineMode = GeometryCombineMode.Intersect;

drawingContext.PushClip(comb);
drawingContext.DrawEllipse(radBrush, null, new Point(Radius, 0), Radius, Radius);
drawingContext.Pop;

p0 = new Point(Radius / 2, 0);
p1 = new Point(Radius / 2, Radius / 2);
p2 = new Point(Radius, Radius / 2);
}
else
{
}

// 绘制中间矩形
drawingContext.DrawRectangle(linearBrush, null, new Rect(Radius - 1, 0, len1 - 2 * Radius + 2, len2));

// 绘制二区弧形
if (EndDir == "Top")
{
}
else
{
EllipseGeometry eGeometry2 = new EllipseGeometry(new Point(len1 - Radius, Radius), Radius, Radius);
RectangleGeometry rGeometry2 = new RectangleGeometry(new Rect(len1 - Radius, 0, Radius, Radius));
CombinedGeometry comb2 = new CombinedGeometry(eGeometry2, rGeometry2);
comb2.GeometryCombineMode = GeometryCombineMode.Intersect;

drawingContext.PushClip(comb2);
drawingContext.DrawEllipse(radBrush, null, new Point(len1 - Radius, Radius), Radius, Radius);
drawingContext.Pop;

// 蚂蚁线坐标点
p3 = new Point(len1 - Radius, Radius / 2);
p4 = new Point(len1 - Radius / 2, Radius / 2);
p5 = new Point(len1 - Radius / 2, Radius);
}

pathFigure.StartPoint = p0;
BezierSegment bezier1 = new BezierSegment(p0, p1, p2, true);
LineSegment line = new LineSegment(p3, true);
BezierSegment bezier2 = new BezierSegment(p3, p4, p5, true);

pathFigure.Segments.Add(bezier1);
pathFigure.Segments.Add(line);
pathFigure.Segments.Add(bezier2);
}

}
else// 垂直方向
{
linearBrush.StartPoint = new Point(0, 0);
linearBrush.EndPoint = new Point(1, 0);
// 两个端点都是垂直的
if (string.IsNullOrEmpty(BeginDir) && string.IsNullOrEmpty(EndDir))
{
drawingContext.DrawRectangle(linearBrush, null, new Rect(0, 0,len2, len1));

Point p0 = new Point(Radius / 2, 0);
Point p1 = new Point(Radius / 2, len1);
pathFigure.StartPoint = p0;
LineSegment lineSegment = new LineSegment(p1, true);
pathFigure.Segments.Add(lineSegment);
}
// 起点垂直,结束端点带方向
elseif (string.IsNullOrEmpty(BeginDir))
{
Point p0;
Point p1;
Point p2;
Point p3;
// 绘制二区弧形
if (EndDir == "Left")
{
EllipseGeometry eGeometry2 = new EllipseGeometry(new Point(0, len1 - Radius), Radius, Radius);
RectangleGeometry rGeometry2 = new RectangleGeometry(new Rect(0, len1 - Radius, Radius, Radius));
CombinedGeometry comb2 = new CombinedGeometry(eGeometry2, rGeometry2);
comb2.GeometryCombineMode = GeometryCombineMode.Intersect;

drawingContext.PushClip(comb2);
drawingContext.DrawEllipse(radBrush, null, new Point(0, len1 - Radius), Radius, Radius);
drawingContext.Pop;

// 蚂蚁线坐标点
p0 = new Point(Radius / 2, 0);
p1 = new Point(Radius / 2, len1 - Radius);
p2 = new Point(Radius / 2, len1 - Radius / 2);
p3 = new Point(Radius, len1 - Radius / 2);

pathFigure.StartPoint = p0;
LineSegment line = new LineSegment(p1, true);
BezierSegment bezier = new BezierSegment(p1, p2, p3, true);

pathFigure.Segments.Add(line);
pathFigure.Segments.Add(bezier);
}
else
{
EllipseGeometry eGeometry2 = new EllipseGeometry(new Point(Radius, len1 - Radius), Radius, Radius);
RectangleGeometry rGeometry2 = new RectangleGeometry(new Rect(0, len1 - Radius, Radius, Radius));
CombinedGeometry comb2 = new CombinedGeometry(eGeometry2, rGeometry2);
comb2.GeometryCombineMode = GeometryCombineMode.Intersect;

drawingContext.PushClip(comb2);
drawingContext.DrawEllipse(radBrush, null, new Point(Radius, len1 - Radius), Radius, Radius);
drawingContext.Pop;

// 蚂蚁线坐标点
p0 = new Point(Radius / 2, 0);
p1 = new Point(Radius / 2, len1 - Radius);
p2 = new Point(Radius / 2, len1 - Radius / 2);
p3 = new Point(0, len1 - Radius / 2);

pathFigure.StartPoint = p0;
LineSegment line = new LineSegment(p1, true);
BezierSegment bezier = new BezierSegment(p1, p2, p3, true);

pathFigure.Segments.Add(line);
pathFigure.Segments.Add(bezier);
}
}
// 起点带方向,结束端点垂直
elseif (string.IsNullOrEmpty(EndDir))
{
}
else
{
// 蚂蚁线坐标点
Point p0;
Point p1;
Point p2;
Point p3;
Point p4;
Point p5;
// 绘制一区弧形
if (BeginDir == "Left")
{
}
else
{

}
// 绘制中间矩形
drawingContext.DrawRectangle(linearBrush, null, new Rect(0, Radius, Radius, len1 - 2 * Radius));

// 绘制二区弧形
pathFigure.StartPoint = p0;
BezierSegment bezier1 = new BezierSegment(p0, p1, p2, true);
LineSegment line = new LineSegment(p3, true);
BezierSegment bezier2 = new BezierSegment(p3, p4, p5, true);

pathFigure.Segments.Add(bezier1);
pathFigure.Segments.Add(line);
pathFigure.Segments.Add(bezier2);
}
}

PathGeometry pathGeometry = new PathGeometry;
pathGeometry.Figures.Add(pathFigure);

Pen pen = new Pen;
pen.Brush = new SolidColorBrush(Colors.Orange);
pen.Thickness = 4;
DashStyle style = new DashStyle;
style.Dashes.Add(3);
style.Dashes.Add(3);
style.Offset = 0;
pen.DashStyle = style;
pen.DashCap = PenLineCap.Round;

DoubleAnimation animation = new DoubleAnimation;
animation.Duration = new Duration(TimeSpan.FromSeconds(0.4));
animation.RepeatBehavior = RepeatBehavior.Forever;
animation.From = FlowDir == FlowDirections.FORWARD ? 0 : -6;
animation.To = FlowDir == FlowDirections.FORWARD ? -6 : 0;
if(Flow)
style.BeginAnimation(DashStyle.OffsetProperty, animation);

drawingContext.DrawGeometry(null, pen, pathGeometry);
}

项目效果

界面色彩协调(主色调为深蓝灰),控件响应灵敏,动效细腻。无论是复杂的多文档界面(基于 AvalonDock 实现的可拖拽布局),还是实时更新的仪表盘、滚动列表,都能保持流畅体验。

常用控件

对标 HandyControl 的开源免费 WPF 控件库 — 高颜值、功能齐全、支持工业场景

按钮

对标 HandyControl 的开源免费 WPF 控件库 — 高颜值、功能齐全、支持工业场景

Shape进度

对标 HandyControl 的开源免费 WPF 控件库 — 高颜值、功能齐全、支持工业场景

电池

对标 HandyControl 的开源免费 WPF 控件库 — 高颜值、功能齐全、支持工业场景

表盘

对标 HandyControl 的开源免费 WPF 控件库 — 高颜值、功能齐全、支持工业场景

电风扇

对标 HandyControl 的开源免费 WPF 控件库 — 高颜值、功能齐全、支持工业场景

数据轮

对标 HandyControl 的开源免费 WPF 控件库 — 高颜值、功能齐全、支持工业场景

管道

对标 HandyControl 的开源免费 WPF 控件库 — 高颜值、功能齐全、支持工业场景

组合控件

对标 HandyControl 的开源免费 WPF 控件库 — 高颜值、功能齐全、支持工业场景

日历

对标 HandyControl 的开源免费 WPF 控件库 — 高颜值、功能齐全、支持工业场景

进度条

对标 HandyControl 的开源免费 WPF 控件库 — 高颜值、功能齐全、支持工业场景

步骤条

对标 HandyControl 的开源免费 WPF 控件库 — 高颜值、功能齐全、支持工业场景

级联选择器

对标 HandyControl 的开源免费 WPF 控件库 — 高颜值、功能齐全、支持工业场景

滚动列表

对标 HandyControl 的开源免费 WPF 控件库 — 高颜值、功能齐全、支持工业场景

树形结构

对标 HandyControl 的开源免费 WPF 控件库 — 高颜值、功能齐全、支持工业场景

提示框

对标 HandyControl 的开源免费 WPF 控件库 — 高颜值、功能齐全、支持工业场景

呼吸灯

对标 HandyControl 的开源免费 WPF 控件库 — 高颜值、功能齐全、支持工业场景

分组

对标 HandyControl 的开源免费 WPF 控件库 — 高颜值、功能齐全、支持工业场景

弹窗

对标 HandyControl 的开源免费 WPF 控件库 — 高颜值、功能齐全、支持工业场景

分页

对标 HandyControl 的开源免费 WPF 控件库 — 高颜值、功能齐全、支持工业场景

标记

对标 HandyControl 的开源免费 WPF 控件库 — 高颜值、功能齐全、支持工业场景

圆形进度条

对标 HandyControl 的开源免费 WPF 控件库 — 高颜值、功能齐全、支持工业场景

统计分析

对标 HandyControl 的开源免费 WPF 控件库 — 高颜值、功能齐全、支持工业场景

项目源码

项目源码托管于 Gitee,结构清晰,注释详实,完整展示了各控件的使用方式。

为了防止丢失,后台回复关键字「WPF工业控件」,即可获取完整源码地址。

对标 HandyControl 的开源免费 WPF 控件库 — 高颜值、功能齐全、支持工业场景

总结

总的来说,控件库填补了 WPF 生态在现代化 UI 组件上的空白。它不像某些重型框架那样臃肿,也不像零散控件那样风格割裂,而是在”实用”与”美观”之间找到了很好的平衡点。

在这个 Web 技术大行其道的时代,WPF 依然在特定领域不可替代。WPF控件库也为.NET 桌面应用,同样可以做得既强劲又好看。

关键词

、、、、、、、、、、、

最后

如果你觉得这篇文章对你有协助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的协助,欢迎随时留言。也可以加入微信公众号[DotNet技术匠]社区,与其他热爱技术的同行一起交流心得,共同成长!

作者:小码编匠

出处:
gitee.com/smallcore/DotNetCore

声明:网络内容,仅供学习,尊重版权,侵权速删,歉意致谢!

END

推荐阅读

觉得有收获?不妨分享让更多人受益

关注「DotNet技术匠」,共同提升技术实力

对标 HandyControl 的开源免费 WPF 控件库 — 高颜值、功能齐全、支持工业场景

收藏

对标 HandyControl 的开源免费 WPF 控件库 — 高颜值、功能齐全、支持工业场景对标 HandyControl 的开源免费 WPF 控件库 — 高颜值、功能齐全、支持工业场景

分享

对标 HandyControl 的开源免费 WPF 控件库 — 高颜值、功能齐全、支持工业场景

在看

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
禺尘的头像 - 鹿快
评论 共2条

请登录后发表评论