65.9K
CodeProject 正在变化。 阅读更多。
Home

错误控件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.63/5 (14投票s)

2008年6月14日

CPOL

7分钟阅读

viewsIcon

49211

downloadIcon

801

扩展错误提供程序、ToolStripErrorDropDown 和 MessageBox 的替代品。

引言

本文将介绍三个工具,它们应该能帮助任何窗体开发人员。它们是

  • 对话框 - 对消息框的改进。
  • 扩展错误提供程序 - 为错误提供程序添加一些附加功能。
  • 工具条错误下拉列表 - 一个与扩展错误提供程序挂钩的控件。

扩展错误提供程序

错误提供程序是一个很棒的工具。任何将其与数据绑定一起使用过的人都知道它有多神奇。然而,它遗漏了如此多简单的东西,这让我感到惊讶。例如,错误提供程序上有多少错误?我最大的问题是——缺乏事件。我想要的两个事件是错误设置时和错误清除时。

错误提供程序也真的很难继承。没有有用的东西被声明为虚方法,所以我们无法覆盖。这意味着我们需要大量使用反射。我认为这带来的性能问题微不足道;然而,更大的问题是我们依赖内部实现而不是公共契约。如果他们改变实现,控件就会停止工作。但是,这种情况不太可能发生,如果我们想添加额外功能,这是唯一的方法。

扩展错误提供程序的实现可以分为三个部分——在使用数据绑定时触发事件、在不使用数据绑定时触发事件,以及其余部分。

不使用数据绑定时触发事件

这部分很简单。我们只需为 SetErrorClear 声明新方法,调用基类,然后触发事件。不需要反射。当然,问题是,如果它被引用为 Error Provider 并且这些方法被调用,那么事件将不会被调用。

使用数据绑定时触发事件

这要困难得多,并且需要了解错误提供程序的实现方式。错误提供程序有一个名为 errorManager 的字段,类型为 BindingManagerBase。它处理绑定。我们需要连接到这些事件,然后触发我们自己的事件。要查看此内容,请查看 WireEvents 方法。另一个问题是在何处订阅这些事件。我们希望在 DataSourceDataMember 更改时订阅它们,因此我们需要声明这些新方法。

我们面临的一个问题是,如果组件正在初始化,我们必须延迟订阅,直到初始化完成。这部分让我很困扰。错误提供程序实现了 ISupportInitialize 接口。然而,它仍然不是一个虚方法。.NET 为我们提供了一个解决方案。通过指定扩展错误提供程序也实现了 ISupportInitialize 并编写一个 EndInit 方法,我们的 EndInit 将被调用,而不是错误提供程序的。我们还希望在连接事件之前运行基类的 EndInit;但是,要做到这一点,我们必须使用反射。

其他一些要做的事情

最后一件事情是实现三个属性:ControlsWithErrorsErrorCountHasErrors。它们的实现非常简单,但我们需要对错误提供程序的实现有一点了解。错误提供程序将控件及其错误消息列表保存在一个名为 itemsHashtable 中,因此通过使用反射获取此 Hashtable,我们可以轻松实现这三个属性。

所以,我们现在有了扩展错误提供程序的实现。但是,它有多大用处呢?嗯,当关闭一个窗体时,你可以快速检查上面是否有错误并显示它们。但是,你的业务对象可能已经能够做到这一点了。嗯,你可以使用 ErrorSet 事件在错误出现时闪烁控件。但是,展示扩展错误提供程序如何使用的最佳示例是工具条错误下拉列表。

工具条错误下拉列表

这不仅仅是一个展示扩展错误提供程序的工具,它确实是一个每当你有一个错误提供程序时都想使用的工具。错误提供程序为错误提供了一个不错的 UI,但是如果你有选项卡会发生什么?我的观点是并非所有错误都能一次性可见。工具条错误下拉列表(如果有人能想到更好的名字,我将不胜感激,我想我已经改名了大约五次,但仍然不满意)解决了这个问题。它位于状态栏中,并提供错误的摘要。此外,当你点击一个错误时,它会聚焦该控件并使其闪烁。这使其成为修复错误的一种非常有用的方法。

那么,你如何使用它呢?只需将其添加到状态栏并设置其 ErrorProvider 属性即可!它已准备就绪。

更多有趣的事情

ErrorTerminology 属性用于将消息从“5 errors”更改为“5 warnings”。它允许我们不仅显示错误,还显示警告。

有一个 AutoSort 属性,它按控件 TabIndex 排序。默认情况下它是 false,因此最新的错误总是出现在底部。还有一个 Sort 方法。在加载后设置初始错误后调用它是一个好主意。

组件上使用的图像是错误提供程序上的图标。

ErrorExamples.JPG

当您点击“Should be Number 1”时,第一个文本框将被选中并闪烁。

对话框

我一直对 Windows 的消息框感到非常失望。它缺少太多有用的功能。很多次,当我收到别人发来的错误消息时,都是消息框的屏幕截图。难道微软真的很难允许文本被选中和复制吗?

另一个问题是,你在消息框中显示多少信息?太多会让用户感到困惑,太少则过于笼统,无法弄清楚发生了什么。而且,找到平衡可能是不可能的。例如,开发人员可能需要堆栈跟踪,但将其作为消息显示给用户什么也说明不了,反而会让他们感到困惑。我为对话框开发的解决方案非常简单。它提供了一条消息和一条扩展消息。扩展消息默认是隐藏的,通过点击“更多详情”显示。

我只使用了一部分图标——错误、信息、警告和问题。我也不允许“无”。在我看来,所有消息都可以归入这四种类型,不添加图标是偷懒,并且提供了更糟糕的界面。消息框的一个问题是这种情况发生得太频繁了,一个主要原因是消息框使得添加图标变得很麻烦。要添加图标,你不仅要指定图标,还要指定按钮(因为按钮参数在图标参数之前)。为了让这更容易,对话框不仅有 Display 方法,还有 DisplayErrorDisplayInformationDisplayQuestion

对话框还有一个复制按钮,方便用户复制所有内容。

我最后一个问题是大小。原因有点难解释,但我希望它能调整大小。

对话框还有一个 UseStandardDialogs 变量,可用于改用消息框。

DialogExamples.JPG

对话框 1:简单,不会让最终用户感到困惑,但没有给我们任何信息,我们也不知道发生了什么。

MessageBox.Show(this, "An unknown error occured", 
                "Error", MessageBoxButtons.OK, 
                MessageBoxIcon.Error);

对话框 2:为开发人员提供了有用的信息,帮助他们弄清楚发生了什么。但对于最终用户来说,这毫无意义,他们不应该被迫看到这些。

MessageBox.Show(this, ex.StackTrace, "Error", 
                MessageBoxButtons.OK, MessageBoxIcon.Error);

对话框 3、4 和 5:对话框默认显示消息 (Dlg3)。用户可以点击“更多详情”获取更多信息 (Dlg 4)。另请注意,与对话框 2 相比,对话框的形状更美观。如果用户认为这样可以使数据更具可读性,则可以调整对话框大小 (Dlg 4)。

DialogBox.DisplayError(this, "An unknown error has occured", ex.StackTrace);

最终想法

我想为扩展错误提供程序添加一个 ErrorDoubleClick 事件,当错误图标被双击时触发。它将允许我显示一个包含错误的对话框。但是,我不知道该怎么做,而且我有一种感觉这不可能。但是,如果有人知道怎么做并且愿意告诉我,我将不胜感激。

另外,DialogBox 中使用的图标显然来自 Windows Vista。我不确定这适用于哪些版权。如果我不应该使用它们,请告诉我,我会找一些替代品。

最后,如果您要投反对票,请留下反馈好吗?我只是觉得很奇怪,人们会说“我不喜欢这个”,然后不给出理由。如果给出理由,我就可以改进组件。

© . All rights reserved.