在鼠标滚轮上禁用 ReportViewer 页面导航

Disable ReportViewer Page Navigation On Mouse Wheel

我有一份报告,其中有很多数据格式适合打印。我的用户平均可以翻阅 16 到 24 页的数据。我决定制作一个 windows 表单 ReportViewer(导入到 WPF 中)并且它工作得很好,除了一件事:我找不到如何禁用滚动时自动翻页。

我查看了我的 rdlc 报告属性和 ReportViewer 两者,但没有看到任何属性。我也无法在网上找到任何信息。这不是可以禁用的功能还是我只是没有看到它?

ReportViewer 通过覆盖名为 ReportPanel 的内部控件的 OnMouseWheel 方法在鼠标滚轮上执行页面导航,因此我们不能覆盖它,因为它是内部的。

ReportViewer 控件有一个 PageNavigation 事件,我们可以用它来取消导航。但是我们应该区分事件是由工具栏按钮还是鼠标滚轮引发的。为此,我们在代码中处理工具栏按钮的 Click 事件(并删除默认事件处理程序)并设置一个标志,稍后将使用该标志来确定工具栏引发的导航事件。

我写了一个方法来封装逻辑并使禁用滚轮导航变得容易。为此,以这种方式调用方法就足够了:

DisableWheelNavigation(reportViewer1);

下面是方法的实现:

public void DisableWheelNavigation(ReportViewer r) {
    bool fromToolbar = false;
    r.PageNavigation += (obj, ea) => {
        if (fromToolbar) fromToolbar = false;
        else ea.Cancel = true;
    };
    var buttons = new string[] { "firstPage", "previousPage", "nextPage", "lastPage" };
    var toolstrip = r.Controls.Find("toolStrip1", true).OfType<ToolStrip>().First();
    toolstrip.Items.OfType<ToolStripButton>()
        .Where(button => buttons.Contains(button.Name)).ToList().ForEach(item => {
            var clickEvent = item.GetType().GetEvent("Click");
            var removeMethod = clickEvent.GetRemoveMethod();
            var d = Delegate.CreateDelegate(clickEvent.EventHandlerType,
                toolstrip.Parent, "OnPageNavButtonClick");
            removeMethod.Invoke(item, new object[] { d });
            item.Click += (obj, ev) => {
                var onPageNavigation = toolstrip.Parent.GetType()
                    .GetMethod("OnPageNavigation",
                BindingFlags.NonPublic | BindingFlags.Instance);
                Action<int> OnPageNavigation = i => {
                    fromToolbar = true;
                    onPageNavigation.Invoke(toolstrip.Parent, new object[] { i });
                };
                if (item.Name == "firstPage") OnPageNavigation(1);
                else if (item.Name == "previousPage") OnPageNavigation(r.CurrentPage - 1);
                else if (item.Name == "nextPage") OnPageNavigation(r.CurrentPage + 1);
                else if (item.Name == "lastPage") {
                    PageCountMode mode;
                    int totalPages = r.GetTotalPages(out mode);
                    if (mode != PageCountMode.Actual) OnPageNavigation(0x7fffffff);
                    else OnPageNavigation(totalPages);
                }
            };
        });
}