WPF 表格控件 ReoGrid 的简单使用

目录

一、概述

二、安装

三、添加控件

四、加载 Excel

五、属性设置

六、支持触摸滚动

七、其它操作

1、显示和隐藏列

2、显示特定字体

八、资源链接

独立观察员 2021 年 7 月 9 日

一、概述

ReoGrid 是一个开源的表格控件库,支持 Winform 和 WPF。本文演示在 WPF 中的使用,用的是直接加载 Excel 的方式,另外解决了触摸滑动的问题。

二、安装

新建好 WPF 项目后,我们使用 NuGet 安装 ReoGrid。直接搜索 “ReoGrid”,选择 unvell.ReoGridWPF,当前最新版是 3.0.0,但是这个版本有点问题,所以我们安装 2.2.0 版本,如下图:

那么 3.0.0 版本有什么问题呢?参见 GitHub 上的一个 issue:https://github.com/unvell/ReoGrid/issues/410 ,简单来说就是拖动滚动条到最边上,3.0.0 版本会出现多余的空白,如果固定了表头,还会看到突出的表头线(这个是 Excel 机制决定的,主要还是空白的问题),如下图:

三、添加控件

在 Xaml 中引入命名空间,然后添加 ReoGridControl:

xmlns:reoGrid="clr-namespace:unvell.ReoGrid;assembly=unvell.ReoGrid"<reoGrid:ReoGridControl x:Name="reoGridControl" Width="Auto" Height="Auto" Margin="0" Readonly="True" SheetTabNewButtonVisible="False" ShowScrollEndSpacing="False" SheetTabVisible="False"/>

设计界面就自动出现预览效果了:

如果取消只读设置,可以直接进行编辑:

四、加载 Excel

我们先在项目中添加一个 Excel,生成操作设置为 Resource(资源):

然后使用如下方法载入 Excel 内容到控件中(在构造函数中调用该方法):

/// <summary>
/// 载入数据
/// </summary>
private void LoadData()
{Dispatcher.BeginInvoke(new Action(() =>{var workbook = reoGridControl;try{using (Stream stream = Application.GetResourceStream(new Uri("/WPFPractice;component/Docs/ 合并中英文对照并换行显示.xlsx", UriKind.Relative)).Stream){workbook.Load(stream, FileFormat.Excel2007);}}catch (Exception ex){_VM.ShowInfo($" 载入用户权限表异常:{ex}");}}));
}

在 ReoGrid 中,ReoGridControl 控件对象就代表了一个 WorkBook,和 Excel 对应。workbook 通过加载 Excel 的文件资源流来呈现内容。

五、属性设置

/// <summary>
/// 设置控件
/// </summary>
private void SetReoGridControl()
{Dispatcher.BeginInvoke(new Action(() =>{// 滚动条设置;//var workbookSettingsDisable = WorkbookSettings.View_ShowScrolls;//reoGridControl.DisableSettings(workbookSettingsDisable);var worksheet = reoGridControl.CurrentWorksheet;worksheet.SelectionStyle = WorksheetSelectionStyle.None; // 选择范围样式;// 冻结行和列;worksheet.FreezeToCell(2, 1, FreezeArea.LeftTop);// 禁用显示行和列头;var worksheetSettingsDisable = WorksheetSettings.View_ShowRowHeader | WorksheetSettings.View_ShowColumnHeader;worksheet.DisableSettings(worksheetSettingsDisable);// 设置只读;var worksheetSettingsEnable = WorksheetSettings.Edit_Readonly;worksheet.EnableSettings(worksheetSettingsEnable);// 设置显示的行数和列数;worksheet.SetCols(3);worksheet.SetRows(13);}));
}

属性设置通常是针对 Worksheet 来进行,可参考官方文档:https://reogrid.net/document/settings/ 。以上方法依次进行了如下操作:去除了选择的样式,冻结了前两行和第一列(固定表头),去除了行和列的序号,设置只读,设置需要显示的行和列范围。效果如下:

可以看到固定了表头后还是会有表头线突出,这是因为窗体(或者说显示范围)比表格内容区域大,实际使用时可通过设置合适的显示大小,ReoGrid 控件会自动出现滚动条,即可解决这个问题(3.0.0 版本不行),如下所示:

可以看到,滚动条滑到最边上,并没有空白出现,也就看不到突出的表头线了。

至于其它的表格样式调整,直接在 Excel 中调整即可(效果和源文件略有差异):

六、支持触摸滚动

到目前为止,在触摸屏下,是只支持触摸滚动条进行内容滚动的,直接在表格内容区进行触摸滚动是没有效果的。这个应该是 WPF 的 ScrollViewer 本身的问题,之前碰到过,网上有人提供过一个方法来解决(通过附加属性)。这里如果要支持表头固定,就要用控件自己添加的 ScrollViewer,也就不能直接用那个方法,所以我改了个专用的方法。各种情况如下:

// 命名空间
xmlns:rg="clr-namespace:unvell.ReoGrid;assembly=unvell.ReoGrid"
xmlns:utils="clr-namespace:WPFPractice.Utils"// 普通使用
<rg:ReoGridControl x:Name="reoGridControl" SheetTabNewButtonVisible="False" ShowScrollEndSpacing="False" SheetTabVisible="False" Readonly="True"/>// 支持触摸滚动(WpfTouchScrollHelper 见 https://gitee.com/dlgcy/WPFTemplate)
<ScrollViewer wpfHelpers:WpfTouchScrollHelper.IsEnabled="True" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"><Grid Width="Auto" Height="Auto"><rg:ReoGridControl Width="1150" Height="2100" x:Name="reoGridControl" SheetTabNewButtonVisible="False" ShowScrollEndSpacing="False" SheetTabVisible="False" Readonly="True"/></Grid>
</ScrollViewer>// 支持触摸滚动 2(ReoGridTouchScrollHelper),兼容固定表头(冻结)
<rg:ReoGridControl Width="Auto" Height="Auto" x:Name="reoGridControl" SheetTabNewButtonVisible="False" ShowScrollEndSpacing="False" SheetTabVisible="False" Readonly="True" Margin="0" utils:ReoGridTouchScrollHelper.IsEnabled="True"/>

其中 ReoGridTouchScrollHelper 的代码如下:

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Input;
using unvell.ReoGrid;namespace WPFPractice.Utils
{/// <summary>/// (参考 WpfTouchScrollHelper 见 https://gitee.com/dlgcy/WPFTemplate)/// 用法:引入命名空间 (比如 util) 后,在 ReoGrid 上写上 util:ReoGridTouchScrollHelper.IsEnabled="True"/// </summary>public class ReoGridTouchScrollHelper : DependencyObject{public static bool GetIsEnabled(DependencyObject obj){return (bool)obj.GetValue(IsEnabledProperty);}public static void SetIsEnabled(DependencyObject obj, bool value){obj.SetValue(IsEnabledProperty, value);}public bool IsEnabled{get { return (bool)GetValue(IsEnabledProperty); }set { SetValue(IsEnabledProperty, value); }}public static readonly DependencyProperty IsEnabledProperty =DependencyProperty.RegisterAttached("IsEnabled", typeof(bool), typeof(ReoGridTouchScrollHelper), new UIPropertyMetadata(false, IsEnabledChanged));public static Dictionary<object, MouseCapture> _captures = new Dictionary<object, MouseCapture>();/// <summary>/// 开关触发事件/// </summary>public static void IsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){var target = d as ReoGridControl;if (target == null) return;if ((bool)e.NewValue){target.Loaded += Target_Loaded;}else{target.Loaded -= Target_Loaded;Target_Unloaded(target, new RoutedEventArgs());}}/// <summary>/// 启用/// </summary>public static void Target_Loaded(object sender, RoutedEventArgs e){var target = sender as ReoGridControl;if (target == null) return;System.Diagnostics.Debug.WriteLine("Target Loaded");target.Unloaded += Target_Unloaded;target.PreviewMouseLeftButtonDown += Target_PreviewMouseLeftButtonDown;target.PreviewMouseMove += Target_PreviewMouseMove;target.PreviewMouseLeftButtonUp += Target_PreviewMouseLeftButtonUp;}/// <summary>/// 禁用/// </summary>public static void Target_Unloaded(object sender, RoutedEventArgs e){System.Diagnostics.Debug.WriteLine("Target Unloaded");var target = sender as ReoGridControl;if (target == null) return;_captures.Remove(sender);target.Unloaded -= Target_Unloaded;target.PreviewMouseLeftButtonDown -= Target_PreviewMouseLeftButtonDown;target.PreviewMouseMove -= Target_PreviewMouseMove;target.PreviewMouseLeftButtonUp -= Target_PreviewMouseLeftButtonUp;}/// <summary>/// 鼠标左键按下/// </summary>public static void Target_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e){var target = sender as ReoGridControl;if (target == null) return;_captures[sender] = new MouseCapture{HorticalOffset = e.GetPosition(target).X,VerticalOffset = e.GetPosition(target).Y,Point = e.GetPosition(target),};}/// <summary>/// 鼠标左键抬起/// </summary>public static void Target_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e){var target = sender as ReoGridControl;if (target == null) return;target.ReleaseMouseCapture();}/// <summary>/// 鼠标移动/// </summary>public static void Target_PreviewMouseMove(object sender, MouseEventArgs e){if (!_captures.ContainsKey(sender)) return;if (e.LeftButton != MouseButtonState.Pressed){_captures.Remove(sender);return;}var target = sender as ReoGridControl;if (target == null) return;var capture = _captures[sender];var point = e.GetPosition(target);var dy = point.Y - capture.Point.Y;var dx = point.X - capture.Point.X;if (Math.Abs(dy) > 5){target.CaptureMouse();}if (Math.Abs(dx) > 5){target.CaptureMouse();}//target.ScrollCurrentWorksheet(capture.HorticalOffset - dx,capture.VerticalOffset - dy);//target.ScrollCurrentWorksheet(dx,dy);target.ScrollCurrentWorksheet(-dx,-dy);}/// <summary>/// 鼠标快照/// </summary>public class MouseCapture{public double VerticalOffset { get; set; }public double HorticalOffset { get; set; }public Point Point { get; set; }}}
}

这样就能通过触摸内容区来进行滚动了。不过,也有缺点,因为滚动条也是在控件范围内,所以有点受影响,不知道大家有没有什么好方法。

七、其它操作

1、显示和隐藏列

比如可以根据用户权限来显示和隐藏列,主要是使用 Worksheet 的 ShowColumns () 和 HideColumns () 方法来设置:

2、显示特定字体

官方文档(https://reogrid.net/document/style/)指明了设置字体的方法:

另外一种方法依然是直接在 Excel 中设置字体。

当然,无论用哪种方法,如果电脑里没有安装该字体,则还是没有效果的,可考虑通过代码自动安装字体(可参考:https://gitee.com/dlgcy/dotnetcodes/blob/cd6d091d3c082ec1f7f450b0e4aec61c6a1ea5cd/DotNet.Utilities/FontHelper.cs)。

八、资源链接

官网文档:https://reogrid.net/document/

GitHub:https://github.com/unvell/ReoGrid

Gitee 克隆:https://gitee.com/DLGCY_Clone/ReoGrid

本文示例:https://gitee.com/dlgcy/Practice/tree/Blog20210709/WPFPractice

WPF

【翻译】WPF 中附加行为的介绍 Introduction to Attached Behaviors in WPF

WPF 使用 Expression Design 画图导出及使用 Path 画图

WPF MVVM 弹框之等待框

解决 WPF 绑定集合后数据变动界面却不更新的问题(使用 ObservableCollection)

WPF 消息框 TextBox 绑定新数据时让光标和滚动条跳到最下面

真・WPF 按钮拖动和调整大小

WPF MVVM 模式下的弹窗

WPF 让一组 Button 实现 RadioButton 的当前样式效果

WPF 原生绑定和命令功能使用指南

WPF 用户控件的自定义依赖属性在 MVVM 模式下的使用备忘

在WPF的MVVM模式中使用OCX组件

第三方库使用

OxyPlot.WPF 公共属性一览

OxyPlot.Wpf 图表控件使用备忘

WPF 表格控件 ReoGrid 的简单使用相关推荐

  1. WPF 用户控件分享之边上带输入框的圆圈

    WPF 用户控件分享之边上带输入框的圆圈 独立观察员 2022 年 8 月 20 日 最近有这样一个需求,有一圈圆形,每个圆形边上有个输入框,以下是完成后的效果图: 拿到这个需求后,分析界面上每个圆形 ...

  2. WPF第三方控件盘点

    WPF统一的编程模型.语言和框架,实现了界面设计人员和开发人员工作可以分离的境界,鉴于WPF强大的优势,且一直是开发者关注的地方,下面和大家分享基于WPF项目开发需要用到的第三方控件,包括业界最受好评 ...

  3. 简单三步!教你用前端表格控件SpreadJS做购物车

    SpreadJS结合40余年专业控件技术和在电子表格应用领域的经验而推出的纯前端表格控件,基于 HTML5,兼容 450 多种 Excel 公式,具备"高性能.跨平台.与 Excel 高度兼 ...

  4. PYQT之表格控件QTableWidget复杂表头(多行表头) 及冻结行的简单方法

    PYQT之表格控件QTableWidget复杂表头(多行表头) 及冻结行的简单方法 表格需要用到复杂表头,查了好久觉得方法不是过于麻烦就是不符合表格要求,经过多方综合,总结超简单方法如下: 1.上下布 ...

  5. WPF Expander控件简单样式

    WPF Expander控件简单样式 样式代码: <Style x:Key="ExpanderStyle1" TargetType="{x:Type Expande ...

  6. clistctrl控件最后插入在后面_用图表控件做一个简单的员工信息查询系统

    前几天在上课的时候有同学说在做人员的信息查询的时候,经常的要去做查找搜索很麻烦,能不能做一个简单的人员信息查询系统,只需要选择人员的编号就可以查询到这个员工的信息.其实要实现这个同学的需求在EXCEL ...

  7. ExtJS4.2学习(10)分组表格控件--GroupingGrid

    分组表格控件在我们的开发中经常被用到,GroupingGrid分组表格就是在普通表格的基础上,根据某一列的数据显示表格中的数据分组的表格控件.举个例子给大家,比如某些信息用树形显示觉得有点大才小用,树 ...

  8. extjs 表单设置html5,ExtJS 配置和表格控件使用

    ExtJS是一套完整的RIA解决方案,也因为功能完整造成了ext-all.js有400多k,由于是基于JS和CSS的功能实现,对客户端机器性能也有一定的要求,即不支持IE6以下的版本.如果您的项目对网 ...

  9. 纯前端表格控件SpreadJS V12.1 隆重登场,专注易用性,提升用户体验

    ​ 一款优秀的开发工具,在更新迭代中,除了要满足不同场景的业务需求,也需不断优化已有功能,尤其是细节方面,要能为用户带来使用体验和开发效率的提升. 作为一款备受业界专家和开发者认可的纯前端类Excel ...

最新文章

  1. 科大奥锐干涉法测微小量实验的数据_光学干涉观测精确丈量宇宙 | 赛先生天文...
  2. 从事前端开发必须要了解的CSS原理
  3. mysql通过存储过程批量造测试数据
  4. linux线程并不真正并行,多核时代:并行程序设计探讨(3)——Windows和Linux对决(多进程多线程)...
  5. 随记:Ubuntu12.04下关闭图形界面的相关问题
  6. mssql 设置自增字段的起始值
  7. B2B2C多用户商城系统源码 Java商城源码
  8. 一文详尽移动互联网广告监测与归因
  9. 看看最新的考试 c语言 noip模拟 纯llq原创作品
  10. 谷歌浏览器Chrome播放rtsp实时视频,并抓图、录像、回放、倍速等
  11. 增强现实技术AR的50个应用场景
  12. table表格tr、td、合并、间距、边框合并、设置边距 代码
  13. 创建、删除ubuntu账户,添加用户到组
  14. base64照片压缩
  15. 天梯赛习题:福到了(递归打印)
  16. 士兵队列训练问题/队列/C语言表达
  17. WEB前端程序员找工作跳槽简历该怎么写?
  18. 判断点是否在四边形内
  19. read the pragmatic programmer -- chapter one
  20. WP Super Cache和W3 Total Cache缓存插件性能总结

热门文章

  1. PDF 补丁丁 (修改PDF书签;拆分、合并、制作PDF;提取图片) 0.3.0.8 正式版
  2. 18.phpmyadmin 4.8.1 远程文件包含漏洞(CVE-2018-12613)
  3. Requests获取连接的IP地址
  4. bzoj2721 [Violet 5]樱花
  5. Codeforces Round #410 (Div. 2) D. Mike and distribution 思维+数学
  6. wamp5.5.12安装re dis扩展
  7. 如何查看自己的ubutu系统是32位的还是64位的
  8. 笔记本本地连接显示电缆拔出_没有安全电缆槽的笔记本电脑如何固定?
  9. 如何在Windows 7、8、10,Vista或XP中删除Windows服务
  10. 如何将Apple Mail建议用于事件和联系人