DialogForm Validation（对话框及表单的确认）

（以下内容，译自Category:Tutorials中的DialogForm Validation. 更多内容可以参看Category:Tutorials部分中文译文及Category:Chinese. ）

用户按了对话框中的OK按钮后，就意味着将要出现某件事情. 不过只有对话框或表单中的数据有效时，事情才会出现. 对话框和表单必须经过 有效性确认. 本专题将描述由PFC GUI支持的有效性确认机制，还要介绍如何使用校验控件integerControl 和 realControl 及如何确认对话框表单中其它的控件.

本文将演示如何确认在对话框或表单中的控件. 首先，要介绍有效性确认的概念. 我们会看到integerControl和realControl是如何使用有效性确认概念的. 接着，我们要考虑在容器控件中的有效性确认问题. 最后，来看几个常用控件的有效性确认，这些控件有：editControl、listBox、新建用户控件.

下载 本文使用的示例工程源文件：


 * Visual Prolog 7.4 和 7.3 IDE下安装示例：
 * Help -> Install Examples...
 * Visual Prolog 7.2 version.
 * Visual Prolog 7.1 version.

有效性确认的概念
有效性确认的概念基础思想是：“控件值应该是有效的”. 有效性的确认发生在对话框或表单中按动OK按钮时，但确认工作也可以由程序安排.

控件负责声明自己的内容是有效的，因此，可以对控件设置有效性确认响应器.

对话框或表单作有效性确认时，是逐个控件依次进行的，但如果结果导致

contentsInvalid(Source, FocusControl, ErrorMessage)

则确认工作就终止了.

integerControl和realControl中的有效性确认
我们来创建一个表单，并用类integerControl和realControl加入两个 custom controls （用户控件）. 可以在提供的示例工程integerControlAndRealControl看到相应的表单结果.

示例生成的代码如下：

integerControl_ctl := integercontrol::new(This), integerControl_ctl:setPosition(92, 4), integerControl_ctl:setSize(60,12), realControl_ctl := realcontrol::new(This), realControl_ctl:setPosition(92, 20), realControl_ctl:setSize(60,12),

还需要加上对 integerControlAndRealControl 表单的调用：

predicates onFileIntegercontrolRealcontrol : window::menuItemListener. clauses onFileIntegercontrolRealcontrol(Source, _MenuTag) :- Form = integerControlAndRealControl::new(Source), Form:show.

运行这个工程，如果输入了非整数值，将会看到一个说明错误的消息框.

我们也可以加入 onOK 响应器来获取确认后的值：

predicates onOk : button::clickResponder. clauses onOk(_) = button::defaultAction :- Integer = integerControl_ctl:getInteger, Real = realControl_ctl:getReal, stdIO::write("Integer value = ",Integer, "\n"), stdIO::write("Real value = ",Real, "\n").

要注意，如果有效性确认不成功，是不会调用 onOK 响应器的，而且该响应器的调用是发生在所有确认谓词之后.

我们来看一下源文件 \pfc\gui\controls\integerControl.pro ，看看有效性确认是如何实现的.

clauses new :- editControl::new, addValidateResponder(onIntValidate).

predicates onIntValidate : validateResponder. clauses onIntValidate(_) = contentsInvalid(This,This, ErrorMessage) :- string(ErrorMessage) = checkContent(getText), !.   onIntValidate(_) = contentsOk.

也就是说，如果局部谓词checkContent认为文本内容是 integer 则确认成功.

上面我们说过，确认工作也可以强制程序安排进行. 可以这样加一个按钮 TryValidation 及相应的代码：

predicates onTryValidation : button::clickResponder. clauses onTryValidation(_Source) = button::defaultAction :- tryValidateWithErrorDialog, !,       stdIO::write("All controls are valid\n"). onTryValidation(_Source) = button::defaultAction.

容器控件中的有效性确认
考查容器控件中的有效性确认，我们先来创建一个这样的控件：在工程中创建一个新的控件fromTo，再在其中加入两个integerControl控件.

考虑到只有当From的值小于To的值控件fromTo</vp>才是有效的，因此可以这样设置fromTo</vp>控件的有效性确认响应器：

predicates validateFromTo : control::validateResponder. clauses validateFromTo (Source) = control::contentsInvalid(Source,from_ctl,     "From value must be less than To value") :- from_ctl:getInteger >= to_ctl:getInteger, !.   validateFromTo (_) = control::contentsOk.

请注意，如果有效性确认不成功，控件 from_ctl</vp> 会得到焦点.

常用控件的有效性确认
我们在工程中创建一个新控件 myControl</vp> ，再创建一个表单并在其中添加三个控件：


 * edit 控件；


 * listbox 控件；


 * myControl</vp> 类的用户控件.

可以在提供的示例usualControls中看到表单的结果.

初始化代码中包含了响应器的设置及对三个控件的初始化内容：

clauses new(Parent) :- formWindow::new(Parent), generatedInitialize, edit_ctl:addValidateResponder(validateEditCtl), listbox_ctl:addList(["First","Second","Third"]), listbox_ctl:addValidateResponder(validateListBox).

有效性确认响应器是这样的：

predicates validateEditCtl : control::validateResponder. clauses validateEditCtl(_) = control::contentsOk :- "OK" = edit_ctl:getText, !.   validateEditCtl(Source) = control::contentsInvalid(          Source, Source,          "Edit control expects to have the text 'OK'").

predicates validateListBox : control::validateResponder. clauses validateListBox(Source) = control::contentsInvalid(         Source,Source,          "Selection of the first row is not allowed") :- 0 = listbox_ctl:tryGetSelectedIndex, !.   validateListBox(_) = control::contentsOk.

predicates validateMyControl : control::validateResponder. clauses validateMyControl(Source) = control::contentsInvalid(         Source,Source,          string::concat("A marker in the ",Missed, " part is mandatory")) :- Missed = toString(isMandatoryMarkNotActive( mandatoryMark, activatedMark)), !.   validateMyControl(_) = control::contentsOk.

可以看到，对控件的有效性确认可以有各种不同的方法.

参考
Category:Tutorials Category:GUI