使用 XML 和 XSLT 管理 ASP.NET 服务器控件、事件处理程序和服务器端验证






4.87/5 (14投票s)
一篇关于使用 XML 和 XSLT 管理 ASP.NET 服务器控件、事件处理程序和服务器端验证的文章。
引言
在大多数情况下,服务器控件在 ASP.NET Web 应用程序中非常有用,因为它们具有一些有价值的事件(例如,点击事件、数据绑定事件、数据已绑定事件等)和许多高级功能,如状态管理、输入验证等。一般来说,XSLT 生成纯 XML 或 HTML,没有任何麻烦,但如果我们想使用 XML 和 XSLT 创建 ASP.NET 服务器控件,那么我们应该遵循一些将在下面描述的步骤。
XML 在 Web 应用程序中用途广泛,当我们结合 XML 和 XSLT 时,它会展现出自己的优势和美丽,这可以大大加快我们的应用程序的速度。使用 XML 的一个主要好处是列的灵活性。假设我们的应用程序中有两种类型的地址:家庭地址和办公地址。这个数字可以随时增加或减少,而无需更改太多代码。并且使用 XSLT,我们不仅可以创建服务器控件,还可以定义它们的事件,这些事件将像魔术一样工作。
要求
我假设本文的读者具备 XML、XSLT 和 ASP.NET 的基本知识。
使用代码
我们将按照以下步骤完成这项工作
- 准备 XML 文档
- 准备 XSLT 文档以转换 XML 数据
- 编写 C# 代码以实例化控件和事件处理程序
考虑以下 XML
<root>
<Employee Id="1">
<Address Caption="Address">
<Home Caption="Home 1">
<Street Caption="Street 1" Type="Text">Road# 27, House# 13, Banani</Street>
<Street Caption="Street 2" Type="Text">
</Street>
<City Caption="City" Type="Text" Required="yes">Dhaka</City>
<Zip Caption="Zip" Type="Text">1213</Zip>
<Country Caption="Country" Type="CountryDDL">BD</Country>
</Home>
<Home Caption="Home 2">
<Street Caption="Street 1" Type="Text">Sector- 10</Street>
<Street Caption="Street 2" Type="Text">Uttara</Street>
<Street Caption="Street 3" Type="Text">
</Street>
<City Caption="City" Type="Text" Required="yes">Dhaka</City>
<Zip Caption="Zip" Type="Text">1230</Zip>
<Country Caption="Country" Type="CountryDDL">BD</Country>
</Home>
</Address>
</Employee>
<Employee Id="2">
<Address Caption="Address">
<Home Caption="Home 1">
<Street Caption="Street 1" Type="Text">J-13, Road 27</Street>
<Street Caption="Street 2" Type="Text">Banani</Street>
<City Caption="City" Type="Text">Dhaka</City>
<Zip Caption="Zip" Type="Text">1213</Zip>
<Country Caption="Country" Type="CountryDDL">BD</Country>
</Home>
<Home Caption="Home 2">
<Street Caption="Street 1" Type="Text">Michigan Avenue</Street>
<Street Caption="Street 2" Type="Text">Suite 2800</Street>
<Street Caption="Street 3" Type="Text">
</Street>
<City Caption="City" Type="Text">Chicago</City>
<Zip Caption="Zip" Type="Text">60601</Zip>
<Country Caption="Country" Type="CountryDDL">USA</Country>
</Home>
</Address>
</Employee>
</root>
我们必须像下面这样显示地址
由于我们的 XML 文档中有多个员工的数据,我们必须在其中选择所请求的员工的数据。为此,我们必须创建一个参数列表,并需要通过 XSLT 参数传递员工 ID。
//create argument list
XsltArgumentList xslArg = new XsltArgumentList();
xslArg.AddParam("employeeId", "", ddlEmployee.SelectedValue);
//load the data
XPathDocument xdoc = new XPathDocument(Server.MapPath("Address.xml"));
//load Xslt
XslCompiledTransform transform = new XslCompiledTransform();
transform.Load(Server.MapPath("DynamicControls.xslt"));
StringWriter sw = new StringWriter();
//transform it
transform.Transform(xdoc, xslArg, sw);
并且,我们将从 XSLT 接收参数,如下所示
<!--<xsl:param name="employeeId"/>-->
<xsl:param name="employeeId"/>
如果我们查看 XML,我们会发现每个节点中都有一个“Caption
”属性。这是显示输出时每个值的标题。另一方面,为了进行输入,有时最好显示下拉列表而不是传统的文本框。例如,当用户必须选择国家名称时,显示国家列表比文本框更有意义。为了实现这个目的,我们在 XML 节点中有一个名为“type
”的类似属性。并且通过检查这个属性,我们可以从 XSLT 呈现适当的 ASP.NET 服务器控件。
<xsl:choose>
<xsl:when test="translate($varType,$up,$lo)='countryddl'">
<asp:DropDownList id="{concat('ddlCountry',$rowindex)}" runat="server"
DataTextField="Text" DataValueField="Value">
<asp:ListItem value="{.}">
<xsl:value-of select="."/>
</asp:ListItem>
</asp:DropDownList>
</xsl:when>
<xsl:otherwise>
<asp:TextBox ID="{$varId}" runat="server"
Text="{.}" width="205px" ></asp:TextBox>
<xsl:if test="translate($isRequired,$up,$lo)='yes'">
<asp:RequiredFieldValidator ErrorMessage="
Required Field" runat="server"
ControlToValidate="{$varId}" />
</xsl:if>
</xsl:otherwise>
</xsl:choose>
最后,我们必须在 XSLT 中声明一个按钮来保存输入数据
<asp:Button ID="btnSaveAddress" runat="server" BackColor="White"
BorderColor="DeepSkyBlue" BorderStyle="Solid"
BorderWidth="1px" Font-Names="Tahoma"
Font-Size="10pt" Text="Save Data" />
现在,我们必须从代码隐藏中为这个按钮设置事件处理程序。ParseControl
函数将通过将 XML 字符串解析为 ASP.NET 服务器控件使我们的工作非常轻松。为了获得新创建的控件的引用,我们必须调用 FindControl
方法。一旦我们获得控件的引用,我们就可以为该控件设置事件处理程序。有一点非常重要的是要知道,添加事件处理程序的过程应该在解析控件之后进行。因为,在解析之前,该控件将不可用。此外,解析应在 Page_Init
事件中进行,以便控件在页面的其余生命周期中可用。
//parse control
Control ctrl = Page.ParseControl(result);
phEmployeeAddress.Controls.Add(ctrl);
//find control to add event handler
Button btnSaveAddress = (Button)phEmployeeAddress.FindControl("btnSaveAddress");
btnSaveAddress.Click += new EventHandler(btnSaveAddress_Click);
我们几乎涵盖了所有内容。最有趣的是,使用 XSLT,我们的 ASPX 页面将变得非常简单和清晰。这是完整的 ASPX 源代码
<%@ Page Language="C#"
AutoEventWireup="true" CodeFile="Default.aspx.cs"
Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Dynamic ASP.net Controls Using Xslt</title>
</head>
<body>
<form id="form1" runat="server">
<div style="float: right; background-color: Yellow">
<asp:Label ID="lblMessage" runat="server"
Text="Label"></asp:Label>
</div>
<div>
<asp:Label ID="Label1" runat="server"
Text="Choose Employee"></asp:Label>
<asp:DropDownList ID="ddlEmployee"
runat="server" Width="128px">
<asp:ListItem Value="1">Ehsan</asp:ListItem>
<asp:ListItem Value="2">Ashraf</asp:ListItem>
</asp:DropDownList>
<asp:Button ID="btnLoadData" runat="server"
BackColor="White" BorderColor="DeepSkyBlue"
BorderStyle="Solid" BorderWidth="1px"
Font-Names="Tahoma" Font-Size="10pt"
Text="Load Data"
OnClick="btnLoadData_Click" /><br />
<br />
<asp:PlaceHolder ID="phEmployeeAddress"
runat="server"></asp:PlaceHolder>
</div>
</form>
</body>
</html>
所有 XSLT 控件都将被提取到 PlaceHolder
,以下是用于呈现 HTML 和服务器控件的整个 XSLT
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:asp="remove">
<xsl:output method="xml" indent="yes"
encoding="utf-8" omit-xml-declaration="yes"/>
<!--<xsl:param name="employeeId"/>-->
<xsl:param name="employeeId"/>
<xsl:template match="/root">
<xsl:for-each select="Employee">
<xsl:if test="@Id = $employeeId">
<table width="100%" border="0"
cellspacing="0" cellpadding="0"
bgcolor="#FFFFFF">
<tbody>
<tr>
<td>
<xsl:apply-templates select="Address">
<!--<xsl:with-param name="count"
select="$count"/>-->
</xsl:apply-templates>
</td>
</tr>
<tr>
<td> </td>
</tr>
<tr>
<td align="right">
<span style="margin-right:20%">
<asp:Button ID="btnSaveAddress"
runat="server" BackColor="White"
BorderColor="DeepSkyBlue" BorderStyle="Solid"
BorderWidth="1px" Font-Names="Tahoma"
Font-Size="10pt" Text="Save Data" />
</span>
<span> </span>
</td>
</tr>
</tbody>
</table>
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template name="HomeAddress"
match="/root/Employee/Address">
<table width="100%">
<tr>
<td height="30" colspan="2" align="left">
<strong>
<xsl:value-of select="@Caption"/>
</strong>
</td>
</tr>
<tr>
<td height="2" colspan="2"
align="left" bgcolor="#CCCC99"></td>
</tr>
<tr>
<td width="50%" height="30"
align="left" valign="top">
<table width="100%" border="0"
cellspacing="0" cellpadding="0">
<tr>
<td colspan="4" height="4"></td>
</tr>
<tr>
<xsl:for-each select="child::*">
<xsl:variable name="rowindex"
select="position()"></xsl:variable>
<td align="left" valign="top">
<table cellpadding="4">
<tr>
<td colspan="4" height="28"
align="left" valign="top">
<strong>
<xsl:value-of select="@Caption"/>
</strong>
</td>
</tr>
<xsl:for-each select="child::*">
<xsl:variable name="varType"
select="@Type"></xsl:variable>
<xsl:variable name="isRequired"
select="@Required"></xsl:variable>
<xsl:variable name="varId"
select="translate(concat(concat(concat(@Caption,'_'),
$rowindex),position()),' ','_')">
</xsl:variable>
<xsl:variable name="up"
select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
<xsl:variable name="lo"
select="'abcdefghijklmnopqrstuvwxyz'"/>
<tr>
<td height="28" align="left" valign="top">
<xsl:value-of select="@Caption"/>
</td>
<td colspan="3" align="left"
valign="top" height="28">
<xsl:choose>
<xsl:when test="translate($varType,$up,$lo)='countryddl'">
<asp:DropDownList id="{concat('ddlCountry',$rowindex)}"
runat="server" DataTextField="Text"
DataValueField="Value">
<asp:ListItem value="{.}">
<xsl:value-of select="."/>
</asp:ListItem>
</asp:DropDownList>
</xsl:when>
<xsl:otherwise>
<asp:TextBox ID="{$varId}"
runat="server" Text="{.}"
width="205px" ></asp:TextBox>
<xsl:if test="translate($isRequired,$up,$lo)='yes'">
<asp:RequiredFieldValidator
ErrorMessage="Required Field" runat="server"
ControlToValidate="{$varId}" />
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</td>
</tr>
</xsl:for-each>
</table>
</td>
</xsl:for-each>
</tr>
</table>
</td>
</tr>
</table>
</xsl:template>
</xsl:stylesheet>
摘要
ASP.NET 服务器控件在 Web 应用程序中非常强大,毫无疑问,通过将 XML 和 XSLT 与其结合,我们可以使 Web 应用程序更强大、更简单、更高效且可重用。此外,通过使用 XML 和 XSLT,应用程序 UI 脚本将看起来更干净,并且更容易维护。我希望这将是一个很好的开始,对于那些希望使用 XML 和 XSLT 以及 ASP.NET 控件的强大功能,使他们的网站更具动态性和结构化的人来说。享受!