WPF 表格控件 ReoGrid 的简单使用

WPF 表格控件 ReoGrid 的简单使用

WPF 表格控件 ReoGrid 的简单使用

独立观察员 2021 年 7 月 9 日

 

一、概述

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

 

二、安装

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

%title插图%num

 

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

%title插图%num

 

三、添加控件

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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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"/>
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"/>
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"/>

 

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

%title插图%num

 

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

%title插图%num

 

四、加载 Excel

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

%title插图%num

 

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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
/// <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}");
}
}));
}
/// <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}"); } })); }
/// <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 的文件资源流来呈现内容。

%title插图%num

 

五、属性设置

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
/// <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);
}));
}
/// <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); })); }
/// <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/ 。以上方法依次进行了如下操作:去除了选择的样式,冻结了前两行和第一列(固定表头),去除了行和列的序号,设置只读,设置需要显示的行和列范围。效果如下:

%title插图%num

 

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

%title插图%num

 

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

 

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

%title插图%num

 

六、支持触摸滚动

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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
//命名空间
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"/>
//命名空间 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"/>
//命名空间
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 的代码如下:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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; }
}
}
}
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; } } } }
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 () 方法来设置:

%title插图%num

 

2、显示特定字体

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

%title插图%num

 

%title插图%num

 

另外一种方法依然是直接在 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

 

原创文章,转载请注明: 转载自 独立观察员(dlgcy.com)

本文链接地址: [WPF 表格控件 ReoGrid 的简单使用](https://dlgcy.com/reogrid-simple-use/)

关注微信公众号 独立观察员博客(DLGCY_BLOG) 第一时间获取最新文章

%title插图%num