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

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.87/5 (14投票s)

2008年4月18日

CPOL

3分钟阅读

viewsIcon

48860

downloadIcon

505

一篇关于使用 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>

我们必须像下面这样显示地址

Article

由于我们的 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>&#160;</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>&#160;</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 控件的强大功能,使他们的网站更具动态性和结构化的人来说。享受!

© . All rights reserved.