1. 初识SunnyUI uiPagination控件第一次接触SunnyUI的uiPagination控件是在开发一个订单管理系统时。当时客户抱怨系统加载5000多条记录时会卡顿近10秒我试过各种传统分页方案都不够理想直到发现了这个宝藏控件。它就像Winform界的瑞士军刀用最简单的配置就能实现专业级的分页效果。uiPagination本质上是一个可视化分页导航器提供页码跳转、页容量调整等核心功能。与Winform原生控件相比它有三大杀手锏一是内置多种UI主题轻松匹配不同系统风格二是支持异步加载数据避免界面卡死三是智能页码计算自动处理首尾页和省略号显示。实测下来相同数据量下页面响应速度提升80%以上。安装方式极其简单通过NuGet包管理器搜索SunnyUI即可获取最新版本。这里有个小技巧建议同时安装SunnyUI.Common基础库某些扩展功能会依赖它。安装完成后工具箱会自动出现一整套SunnyUI控件组找到那个带着页码图标的小方块就是我们的主角了。2. 基础配置三步走2.1 属性面板调参实战拖拽控件到窗体后属性面板里这些参数需要特别关注PageSize默认值10建议根据屏幕高度动态计算。比如DataGridView显示15行刚好满屏就可以设为15TotalCount这个要放在代码里动态赋值后面会详细讲ShowPageSizeList设为true会显示下拉框让用户自由切换每页条数PageSizeList格式如10,20,50,100注意最后一个值建议放全部选项我习惯在窗体Load事件里初始化基础配置uiPagination1.PageSize 15; uiPagination1.ShowPageSizeList true; uiPagination1.PageSizeList 15,30,50,全部;2.2 事件绑定要诀控件提供两个关键事件PageChanged页码变化时触发PageSizeChanged页容量变化时触发建议用Lambda表达式简化代码uiPagination1.PageChanged (sender, paging) { BindData(paging.PageIndex, paging.PageSize); };这里有个坑要注意当PageSizeChanged触发时PageIndex会自动重置为1。很多开发者会忘记处理这个细节导致显示异常。正确的做法是在事件里强制刷新数据uiPagination1.PageSizeChanged (sender, paging) { uiPagination1.PageIndex 1; // 重置页码 BindData(1, paging.PageSize); // 从第一页加载 };3. 数据绑定高阶技巧3.1 与DataGridView的黄金组合实际项目中最常见的场景是分页表格。假设我们有个订单表OrderInfo使用Dapper做ORM查询private void BindData(int pageIndex, int pageSize) { string sql SELECT * FROM OrderInfo ORDER BY CreateTime DESC; var pagedSql ${sql} OFFSET {(pageIndex - 1) * pageSize} ROWS FETCH NEXT {pageSize} ROWS ONLY; using (var conn new SqlConnection(connStr)) { var data conn.QueryOrderInfo(pagedSql); dataGridView1.DataSource data; // 关键步骤设置总记录数 uiPagination1.TotalCount conn.ExecuteScalarint($SELECT COUNT(1) FROM OrderInfo); } }这里用到了SQL Server 2012的OFFSET-FETCH语法比传统的ROW_NUMBER()方案性能更好。如果是MySQL可以改用LIMIT语法。3.2 内存分页方案当数据量不大比如万条以内时也可以考虑内存分页。我在一个展会签到系统中这样实现private ListAttendee _allAttendees; private void LoadAllData() { _allAttendees GetAttendeesFromAPI(); // 从API获取全部数据 uiPagination1.TotalCount _allAttendees.Count; ApplyPaging(); } private void ApplyPaging() { dataGridView1.DataSource _allAttendees .Skip((uiPagination1.PageIndex - 1) * uiPagination1.PageSize) .Take(uiPagination1.PageSize) .ToList(); }这种方案的优点是减少数据库查询次数适合数据变化不频繁的场景。记得在数据变更时要手动调用ApplyPaging()刷新显示。4. 样式定制与用户体验4.1 主题切换秘籍SunnyUI最让人惊喜的是它的主题系统。只需一行代码就能切换整套配色uiPagination1.Style UIStyle.Blue; // 可选Orange/Red/Green等十余种风格如果想深度定制可以修改这些属性ButtonFillColor页码按钮背景色ButtonForeColor页码文字颜色ActiveColor当前选中页样式HoverColor鼠标悬停效果建议在夜间模式系统中使用深色主题if (isNightMode) { uiPagination1.Style UIStyle.Black; uiPagination1.ButtonFillColor Color.FromArgb(40, 40, 40); }4.2 响应式布局技巧当窗体大小变化时分页控件可能会显得拥挤。我通常这样处理private void Form1_Resize(object sender, EventArgs e) { uiPagination1.Width this.ClientSize.Width - 40; uiPagination1.Location new Point( (this.ClientSize.Width - uiPagination1.Width) / 2, uiPagination1.Location.Y); }对于超宽屏用户还可以启用ShowTotalCount和ShowPageCount属性在两侧显示统计信息让布局更平衡。5. 性能优化实战5.1 大数据量处理方案当面对百万级数据时传统分页会遇到性能瓶颈。我的解决方案是使用存储过程预编译分页查询添加CreateTime字段的聚集索引实现后台线程加载数据优化后的代码结构private async void BindDataAsync(int pageIndex, int pageSize) { uiPagination1.Enabled false; // 禁用操作 loadingIndicator.Show(); await Task.Run(() { var result QueryBigData(pageIndex, pageSize); this.Invoke(new Action(() { dataGridView1.DataSource result.Data; uiPagination1.TotalCount result.TotalCount; })); }); loadingIndicator.Hide(); uiPagination1.Enabled true; }5.2 缓存策略对于相对静态的数据可以引入内存缓存。我常用的模式是private MemoryCache _cache new MemoryCache(PaginationCache); private DataPage GetDataWithCache(int pageIndex, int pageSize) { string cacheKey $data_{pageIndex}_{pageSize}; return _cache.GetOrCreate(cacheKey, entry { entry.AbsoluteExpiration DateTime.Now.AddMinutes(5); return QueryFromDatabase(pageIndex, pageSize); }); }记得在数据修改时清空相关缓存private void UpdateOrder(Order order) { SaveToDatabase(order); _cache.Remove(data_*); // 通配符清除所有分页缓存 }6. 常见问题排查6.1 页码显示异常经常有开发者反馈页码错乱通常是这两个原因没有正确设置TotalCount在数据加载完成前就修改了PageIndex正确的处理流程应该是查询总记录数 → 设置TotalCount → 加载当前页数据使用try-catch包裹数据库操作6.2 数据重复或缺失这往往是由排序不一致导致的。确保做到分页SQL必须有明确的ORDER BY排序字段应该建立索引避免使用非稳定排序如只按时间排序可能漏数据一个可靠的排序方案示例SELECT * FROM Products ORDER BY CategoryID, ProductName, ProductID -- 最后用主键保证稳定性 OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY7. 扩展应用场景7.1 主从表联动分页在订单明细系统中我这样实现主子表联动private void uiPagination_Order_PageChanged(object sender, UIPagingEventArgs e) { var order GetCurrentOrder(); uiPagination_Detail.TotalCount order.Details.Count; BindDetailData(); }7.2 跨窗体分页同步通过自定义事件实现多窗体数据同步// 在主窗体定义事件 public event Actionint, int PaginationChanged; // 子窗体订阅事件 mainForm.PaginationChanged (pageIndex, pageSize) { uiPagination1.PageIndex pageIndex; uiPagination1.PageSize pageSize; };这种模式在MDI应用中特别有用能保持各视图的分页状态一致。