支持 AJAX 的可折叠表单部分






3.57/5 (4投票s)
一个 AJAX 控件,可以隐藏或显示表单的一部分,包括处理嵌套在该部分中的验证器。
引言
在许多情况下,我们可能需要实现复杂的表单,其中包含多个部分,这些部分可以根据用户的输入进行隐藏或显示。
在这些场景中遇到的问题是,我们想要隐藏或显示的部分可能包含必须禁用的验证器,以便表单能够回发。这可以通过服务器端代码轻松实现,但这会涉及一次往返服务器的行程,为了性能考虑,我们希望避免这种情况。
要使用 JavaScript 禁用验证器,我们必须保留所有验证器的引用,并且在隐藏表单的一部分时,必须禁用所有验证器,在显示它时,必须重新启用它们。
此控件旨在让所有这些工作对开发人员透明。开发人员唯一需要做的是将其添加到表单中,并将所有控件及其验证器嵌入其中。然后,它会处理所有必需的嵌套验证器的启用/禁用,以及显示/隐藏其中的所有控件。
例如,考虑以下表单
当用户单击复选框时,我们也希望显示表单的第二部分
已知新显示的三个字段是必填的,如果我们不在隐藏表单底部时禁用它们的验证器,它将不会回发,实际上,由于那些将包含在隐藏的 DIV
中,它甚至不会显示验证错误消息。
使用代码
从客户端角度看
此控件是一个 AJAX 控件,这意味着页面上的每个控件实例都将生成一个相应的 AJAX (JavaScript) 对象实例,该实例基于 'AjaxCollapsibleFormSection.js' 文件中定义的组件。
基本上,它是一个具有几个属性和必要算法来显示和隐藏表单部分的组件。之所以使用 AJAX 组件模型来实现它,是因为我们希望在文件中能够拥有一个以上的可折叠部分,因此,在 JavaScript 端,每个实例都应该有自己的验证器列表和其他属性。因此,最好的方法是拥有一个代表一个具有所有嵌入属性(这只是封装原则)的部分的 JavaScript 对象。
要使控件启用 AJAX,我们必须实现 IScriptControl
接口,该接口包含两个成员。一个用于获取 JavaScript 文件的引用,另一个用于 ScriptControlDescriptor
对象列表。
此控件的 ScriptControlDescriptor
非常简单,因为它包含以下属性
Validators
:所有验证器 ID 的数组。GroupName
:一个任意字符串,用于在页面上将部分组合在一起,并使其外观互斥(显示一个部分时,具有相同组名的其他所有部分都将被隐藏)。Exclusive
/Inclusive
IsVisibleSection
ShowHideControl
:这是一个ElementProperty
,这意味着它将转换为指向复选框的 JavaScript 对象引用,其状态将显示或隐藏该部分。ShowControl
:指向单选按钮的引用,选中该单选按钮时将显示该部分。HideCoontrol
:指向单选按钮的引用,选中该单选按钮时将隐藏该部分。
以下是实现 IScriptControl
接口的代码
IEnumerable<ScriptDescriptor> IScriptControl.GetScriptDescriptors()
{
ValidateShowHideControls();
ScriptControlDescriptor desc =
new ScriptControlDescriptor("SABBEL.Web.Controls" +
".Ajax.CollapsibleFormSection", this.ClientID);
string[] validatorsArray = new string[_validators.Count];
_validators.CopyTo(validatorsArray, 0);
desc.AddProperty("Validators", validatorsArray);
desc.AddProperty("GroupName", GroupName);
desc.AddProperty("Exclusive", Exclusive);
desc.AddProperty("Inclusive", Inclusive);
desc.AddProperty("IsVisibleSection", IsVisibleSection);
if (ShowHideControl!=null)
desc.AddElementProperty("ShowHideControl", ShowHideControl.ClientID);
if (HideControl != null)
desc.AddElementProperty("HideControl", HideControl.ClientID);
if (ShowControl != null)
desc.AddElementProperty("ShowControl", ShowControl.ClientID);
yield return desc;
}
IEnumerable<ScriptReference> IScriptControl.GetScriptReferences()
{
ScriptReference reference = new ScriptReference(
"SABBEL.Web.Controls.Ajax.AjaxCollapsibleFormSection.js",
"SABBEL.Web.Controls.Ajax");
yield return reference;
}
在 JavaScript 端,“SABBEL.Web.Controls.Ajax.CollapsibleFormSection
”类有几个方法。其中最重要的是 ShowHide
,它将根据第一个参数的值来显示或隐藏该部分。此方法将依次调用“ResetValidators
”来启用或禁用验证器,具体取决于我们是显示还是隐藏该部分。
另一个方法“InitializeCollapsibleForms
”被注册为在 AJAX Toolkit 加载后立即启动。这是通过调用 add_load
方法实现的。
Sys.Application.add_load(InitializeCollapsibleForms);
也就是说,一旦整个页面加载完成,它将检查页面中的所有部分,并根据控制它们的控件(复选框或单选按钮)的状态初始显示或隐藏它们。
在 JavaScript 文件中,您还可以找到在选中或取消选中复选框或单选按钮时调用的函数。这些函数的名称可以通过将名称传递给节控件来更改。有三个函数可以重命名(这样您就可以重写它们并添加任何额外的显示/隐藏前/后事件或处理)
属性名 |
默认值 |
JS 函数的签名 |
|
|
|
|
|
|
|
|
|
如果您决定重命名函数并重写它们,签名必须与上表中的相同。您可以从服务器控件附带的 JavaScript 文件中提供的默认实现开始。
从服务器端角度看
在服务器端,此控件会解析所有子控件以查找任何验证器。所有验证器客户端 ID 都将保留在一个数组中,并通过其“Validators
”属性传递给 AJAX 对象引用。如果“Recursive
”属性设置为 true
,则控件将递归解析子控件。这可能会影响性能,因此,默认情况下,Recursive
属性设置为 false
。
此外,它还会向已与该部分关联的复选框或单选按钮添加 JavaScript 事件处理程序。
就是这样。如您所见,大部分工作都在客户端使用 AJAX 组件完成,如上所述。
如何使用此控件
在页面中,只需用 AjaxCollapsibleFormSection
控件将您想要按需隐藏和显示的表单部分括起来,并指定哪个控件将触发显示和/或隐藏事件;在下面的示例中,控件是 CheckBox
(checkbox1
)。
<asp:CheckBox runat="server"
Text="show this section" ID="checkbox1" />
<cc1:AjaxCollapsibleFormSection ID="AjaxCollapsibleFormSection1"
ShowHideControlName="checkBox1"
GroupName="Group1"
Exclusive="true"
ShowHideEventHandler="showHideFormExclusive"
runat="server">
<asp:RequiredFieldValidator ID="rfvFirstName"
runat="server"
ErrorMessage="First Name is mandatory"
ControlToValidate="firstName"/>
First Name: <asp:TextBox runat="server" ID="firstName">
</asp:TextBox><br />
<asp:RequiredFieldValidator ID="RequiredFieldValidator1"
ErrorMessage="Last Name is mandatory"
runat="server" ControlToValidate="lastName"/>
Last Name: <asp:TextBox runat="server" ID="lastName">
</asp:TextBox><br />
<asp:RequiredFieldValidator ID="RequiredFieldValidator2"
runat="server" ErrorMessage="Street address is mandatory"
ControlToValidate="address" />
Street Address: <asp:TextBox runat="server" ID="address">
</asp:TextBox><br />
</cc1:AjaxCollapsibleFormSection>
示例应用
在示例应用程序中,有关于独占部分和递归控件的用法示例,以防该部分中包含嵌套的用户控件。
结论
这个控件对我以及我们的团队来说非常有用,因为我们可以非常轻松地使我们的表单更具动态性,而无需在每次需要折叠或显示其某个部分(因为验证器)时都要发布页面。起初,我们开始用旧的方式编写 JavaScript,使用数组列表和内联 JavaScript 来跟踪验证器 ID 等。但是,这个解决方案更加优雅和可重用,当然,作为面向对象,也更容易维护。
这是使用 AJAX 启用的控件可以实现的良好示例。关于 AJAX 控件还有很多可以说的,但希望这个能成为一个很好的起点。
一个增强功能是让这个控件与复选框和单选按钮解耦,并允许任何其他 Web 控件触发它;例如,我们可以有一个链接来显示该部分,并在页面上有一个链接来隐藏它。或者它可以是一个按钮、一个图像……