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 圖表控件使用備忘
總結
以上是生活随笔為你收集整理的WPF 表格控件 ReoGrid 的简单使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: FastTunnel - 打造人人都能搭
- 下一篇: 来聊聊正则表达式