在鼠标滚轮上禁用 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);
}
};
});
}
我有一份报告,其中有很多数据格式适合打印。我的用户平均可以翻阅 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);
}
};
});
}