WPF 表格控件 ReoGrid 的简单使用

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 图表控件使用备忘

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/300679.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

史上最牛空姐,从飞机上掉下愣是没摔死

全世界只有3.14 % 的人关注了青少年数学之旅珠穆朗玛峰最新的测量高度为8844米&#xff0c;人是血肉之躯&#xff0c;一旦从这么高的地方掉下来&#xff0c;别说生还了&#xff0c;能有个全尸就不错了。但是&#xff0c;历史上却有这么以为超级幸运的女人&#xff0c;她从比珠穆…

mysql主主同步冲突_MySQL主主同步主键冲突处理

两台数据库都报slave同步失败了&#xff0c;先说明一下环境&#xff0c;架构&#xff1a;lvskeepalivedamoebamysql&#xff0c;主主复制&#xff0c;单台写入&#xff0c;主1:192.168.0.223(写)主2:192.168.0.230好吧&#xff0c;先show slave status \G看一下同步失败的具体报…

[未来的购碟指南]送给那些以后想收藏真人电影DVD的菜鸟们

随着真人电影在全世界的上映&#xff0c;全世界又掀起了一股新的TF热。对于我们这些铁杆FANS来说&#xff0c;除了肯定要去电影院观影之外&#xff0c;肯定还要收藏一张这部电影的DVD&#xff0c;以达到圆满。本人从2002年开始收藏各种DVD&#xff0c;因此这几年中&#xff0c;…

来聊聊正则表达式

概念正则表达式 是一种匹配输入文本的模式。.Net框架提供了允许这种匹配的正则表达式引擎。模式由一个或多个字符、运算符和结构组成。Regex 类Regex 类用于表示一个正则表达式。下表列出了 Regex 类中一些常用的方法&#xff1a;1 public bool IsMatch( string input ) 指示 R…

nginx对websocket的支持及uliweb chatroom的测试

2019独角兽企业重金招聘Python工程师标准>>> 在尝试在uliweb中使用gevent开发聊天室时&#xff0c;已经在网上搜到nginx是支持websocket的代理的&#xff0c;不过应该不支持集群模式。不过当时没有试过&#xff0c;今天试了一下&#xff0c;在普通的反向代理是没有问…

为什么祖国没有农历生日? | 今日最佳

世界只有3.14 % 的人关注了青少年数学之旅假期计划路线所以为什么没有农历生日所以这个到底是什么字&#xff1f;身体不适&#xff0c;去了趟医院那医生怎么说&#xff1f;......你还敢说养我吗&#xff1f;&#xff08;图源网络&#xff0c;侵权删&#xff09;

ios中amplify配置configure_Nginx源码编译安装及配置文件初步学习

通过源码编译安装。nginx.org #官网地址 # 安装过程 wget http://nginx.org/download/nginx-1.18.0.tar.gz -P /usr/src # tar文件用tar命令解压 tar -zxvf nginx-1.18.0.tar.gz关于wget的-P参数&#xff0c;manual中的解释是prefix&#xff0c;Set directory prefix …

RFID会议签到系统总结(二十一)――服务端的通讯

<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />这一篇其实没什么可讲的&#xff0c;只提一下跟客户端不太一样的一些地方。 服务端跟客户端最大的区别是它面对的不是单单一个连接&#xff0c;而是有一些个连接。对于接收与发送…

演示: 动态NAT完成网络地址翻译

演示&#xff1a; 动态NAT完成网络地址翻译技术交流与答疑请加入群&#xff1a;1952289演示目标&#xff1a;使用动态NAT完成对私有网络的地址翻译。演示环境&#xff1a;如下图9.63所示。演示背景&#xff1a;该演示环境保持PAT演示环境的网络基础配置&#xff0c;然后使用动态…

.NET测试用例写的好不好?让变种来测试一下!

为了保证代码能够正常工作&#xff0c;我们常常编写了大量单元测试&#xff0c;并且代码覆盖率也做到了100%。但是在生产环境运行时还是会出问题&#xff01;为什么&#xff1f; 这是因为你没有进行变异测试&#xff01;变异测试变异测试就是把bug&#xff08;变种mutant&#…

你根本想象不到,学霸到底经历过什么

全世界只有3.14 % 的人关注了青少年数学之旅在微信的订阅号中&#xff0c;每人最多有12个常读公众号。可公众号这么多&#xff0c;哪些公众号值得关注呢&#xff1f;今天给大家推荐的几个公众号&#xff0c;不仅生产优质的时效性内容&#xff0c;还会提供各种多元化的内容角度&…

mysql重装远程服务未_MySQL远程连接丢失问题解决方法(Lost connection to MySQL server)...

最近服务器很不稳定&#xff0c;于是重装了mysql 和php 服务&#xff0c;但是接着却遇到了很头疼的麻烦。远程连接mysql是总是提示&#xff1a;Lost connection to MySQL server at ‘reading initial communication packet, system error: 0很明显这是连接初始化阶段就丢失了连…

买基金如何开户

开户主要有两种途径&#xff1a;&#xff08;1&#xff09;投资者通过深交所交易系统认购、买入或卖出上市开放式基金须使用深圳A股账户或深圳证券投资基金账户&#xff08;以下简称“深圳证券账户”&#xff09;。投资者可通过中国结算公司深圳分公司的开户代理机构&#xff0…

OpenStack开启亚洲之旅

11月5-8日&#xff0c;OpenStack峰会在中国香港亚洲国际博览馆举行。这是OpenStack峰会首次在北美地区之外举行&#xff0c;吸引了约3000名全球各地的企业、用户和开发者。中国已经是除美国以外OpenStack软件下载量和对社区贡献代码量第二大的地区。OpenStack峰会此次落户香港也…

历史上最怪异的23种飞行器,设计者脑子里都想什么了

全世界只有3.14 % 的人关注了青少年数学之旅历史的长河中有无数稀奇古怪&#xff08;呆萌&#xff09;的发明被无情淘汰&#xff0c;而飞行器的发明可谓人类探索道路上尤为浓烈的一笔&#xff0c;过去的110多年里&#xff0c;空中就曾出现以下23中古怪的飞行器。下面这张图比较…

NET问答: 如何让 HttpClient 支持 Http 2.0 协议?

咨询区 Justin Lessard&#xff1a;我的一个项目需要支持 Http 2.0 进行数据的收发&#xff0c;目前用的项目版本是 .NET Core 2.2&#xff0c;我选型了 HttpClient&#xff0c;但是我发现一个问题&#xff0c;在生产环境中的程序返回的 response 版本一直都是 Http 1.1&#x…

最近读的书与做的事

做的事情无非是Thesis当头&#xff0c;其他跟上。Axss的工作室站点&#xff0c;还有就是IAESTE项目的部分页面。读的书&#xff1a;《深入探索C/C》&#xff1a;搞清楚以前很多一知半解的概念《Game Programming Gem 3》&#xff1a;对我而言仍是太深了点&#xff0c;不过当作了…

从mysql读取图片_如何从sql数据库内读取图片

privatevoidSHOW(){MemoryStreamstreamnewMemoryStream();byte[]buffBytenull;stringsqlstr"selectRefFinImagefromRefTablewhereRefId5";//我要规定死读入第五张图片SqlConnectio...private void SHOW(){MemoryStream stream new MemoryStream();byte[] buffByte …

邮件发送类,支持Gmail

邮件发送类,支持Gmail&#xff0c;使用简单方便 usingSystem;usingSystem.Collections.Generic;usingSystem.Text;usingSystem.Net;usingSystem.Net.Mail;namespaceLZ2007.Function...{ /**//// <summary> /// 邮件发送类 /// <CreateDate>2007/07/02<…

和爸爸的聊天永远是个谜。。 | 今日最佳

世界只有3.14 % 的人关注了青少年数学之旅【1】【2】【3】【4】【5】【6】【7】【8】【9】【10】【11】【12】【13】【14】【15】【16】【17】【18】【19】【20】【21】【22】【23】【24】&#xff08;图源网络&#xff0c;侵权删&#xff09;