asp.net夜话之十:复合控件和母板页---(下)


下面是一个用javascript来实现的选项卡式效果的例子,完全采用输出HTML代码的方式。在这个例子中我们通过css和div来控制当前活动选项卡和非活动选项卡的显示与否及显示样式,疑难部分笔者都做了详尽注释,读者朋友完全可以根据自己的实际需要把代码改造成自己想要的效果。

  以下是设计部分代码:

<%@PageLanguage="C#"AutoEventWireup="true"CodeFile="JavaScriptMenu.aspx.cs"Inherits="JavaScriptMenu"%>
<!DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.0Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<htmlxmlns="http://www.w3.org/1999/xhtml">
<headrunat="server">
  <title>JavaScript实现的选项卡式效果</title>
  <scriptlanguage="javascript"type="text/javascript">
  functionShow_Sub(id_num,num,obj)
  { 
    for(vari=0;i<=9;i++)
    {
      if(GetObj("tabb"+id_num+i))
      {
        GetObj("tabb"+id_num+i).className='guide2';
      }
      if(GetObj("subb"+id_num+i))
      {
        GetObj("subb"+id_num+i).style.display='none';
      }
    }
    if(GetObj("tabb"+id_num+num))
    {
      GetObj("tabb"+id_num+num).className='guide1';
    }
    if(GetObj("subb"+id_num+num))
    {
      GetObj("subb"+id_num+num).style.display='block';
    }
  }
  functionGetObj(objName)
  {
    if(document.getElementById)
    {
      returneval('document.getElementById("'+objName+'")');
    }
    else
    {
      returneval('document.all.'+objName);
    }
  }
</script>
<styletype="text/css">
.guide1{
cursor:hand;
color:#003399;
background-color:#3399FF;
font-weight:bold;
text-decoration:none;
border-right:1pxsolid#A2C0FE;
height:25px;
line-height:25px;
}
.guide2{
cursor:hand;
border-right:1pxsolid#A2C0FE;
line-height:25px;
}
.24line{line-height:24px;}
.pad5{padding:5px;}
.padtop2{padding-top:2px;}
.padtop5{padding-top:5px;}
.t{border-top:1pxsolid#A2C0FE;}
.b{border-bottom:1pxsolid#A2C0FE;}
.l{border-left:1pxsolid#A2C0FE;}
.r{border-right:1pxsolid#A2C0FE;}
.right{
float:right;
color:#999999;
}
.left{
float:left;
color:#999999;
}
</style>
</head>
<body>
  <formid="form1"runat="server">
  <div>
  <%=GetUserPanel(0)%>
  </div>
  </form>
</body>
</html>

  下面是后台代码:

usingSystem;
usingSystem.Data;
usingSystem.Configuration;
usingSystem.Collections;
usingSystem.Web;
usingSystem.Web.Security;
usingSystem.Web.UI;
usingSystem.Web.UI.WebControls;
usingSystem.Web.UI.WebControls.WebParts;
usingSystem.Web.UI.HtmlControls;
usingSystem.Text;
usingSystem.Data.SqlClient;
publicpartialclassJavaScriptMenu:System.Web.UI.Page
{
  protectedvoidPage_Load(objectsender,EventArgse)
  {
  }
  //在本页面中多次要查询数据库,为了简单起见,把对数据库的查询操作提出来作为一个单独的方法
  //这个方法会根据查询SQL语句的不同而返回不同数据的DataTable
  privateDataTableGetDataTable(stringsql)
  {
    SqlConnectionconnection=newSqlConnection("DataSource=(local);InitialCatalog=AspNetStudy;PersistSecurityInfo=True;UserID=sa;Password=sa");
    SqlCommandcommand=newSqlCommand(sql,connection);
    SqlDataAdapteradapter=newSqlDataAdapter(command);
    DataTabledata=newDataTable();
    adapter.Fill(data);
    returndata;
  }
  ///<summary>
  ///按照UserName字段的首字母顺序查找用户,并以类似于选项卡的方式显示出来
  ///说明:在实际项目中可能一个页面要输出多个选项卡式效果,可以以不同的type来区分
  ///以达到公用一个方法的目的
  ///</summary>
  ///<paramname="type">类别编号</param>
  ///<returns></returns>
  publicstringGetUserPanel(inttype)
  {
    //因为多次需要操作字符串,为提高性能使用了System.Text.StringBuilder类而非string类
    StringBuildertext=newStringBuilder(4096);
    //表头
    text.AppendLine("<!--------start----->");
    text.AppendLine("<tablewidth="400"border="0"cellspacing="0"cellpadding="0">");
    text.AppendLine("<tr>");
    text.AppendLine("<tdheight="168"valign="top"class="padtop2"><tablewidth="100%"border="0"cellspacing="0"cellpadding="0">");
    text.AppendLine("<tr>");
    text.AppendLine("<tdheight="168"valign="top"class="pad524linebltr">n<tablewidth="100%"border="0"cellspacing="0"cellpadding="0">");
    text.AppendLine("<tr>");
    text.AppendLine("<td><tablewidth="100%"border="0"cellpadding="0"cellspacing="0"class="ltb">n");
    text.AppendLine("<tr>");
    //这里仅列出UserName字段首字母为'c','d','l','z'的用户
    char[]firstChar=newchar[]{'c','d','l','z'};
    #region输出选项卡标签
    for(inti=0;i<firstChar.Length;i++)
    {
      text.AppendLine("<td class="guide"+((i+1)>=2?2:1)+""id="tabb"+type+""+i+""onmousemove=Show_Sub("+type+","+i+",this)align="center">"+firstChar[i]+"</td>");
    }
    #endregion
    text.AppendLine("</tr></table>");
    text.AppendLine("</td></tr><tr><tdclass="padtop5">");
    #region输出每个选项卡下的用户
    for(inti=0;i<firstChar.Length;i++)
    {
      if(i==0)
      {
        text.AppendLine("<divid="subb"+type+i+"" class="24line">n");
      }
      else
      {
        text.AppendLine("<divid="subb"+type+i+"" style="DISPLAY:none" class="24line">n");
      }
      DataTabledataPersonList=GetDataTable("selectUserName,RealNamefromUserInfowhereUserNamelike'"+firstChar[i]+"%'");
      DataRowrow=null;
      //输出每个用户的信息
      for(intj=0;j<dataPersonList.Rows.Count;j++)
      {
        row=dataPersonList.Rows[j];        
        text.AppendLine("<divclass="left">"+row["UserName"].ToString()+"</div>");
        text.Append("<divclass="right">"+row["RealName"].ToString()+"</div>");
        text.AppendLine("</br>");
      }
      text.AppendLine("</div>");
    }
    #endregion
    text.AppendLine("</td>n</tr>n</table>n</td>n</tr></table></td></tr></table>");
    text.AppendLine("<!------end--->");
    returntext.ToString();
  }
}

  这个程序显示效果如下:

  点击“z”选项卡时的效果:

  用Javascript实现的选项卡式效果比用MultiView控件实现同样的效果要复杂很多,但是它有一个有点就是在选项卡之间切换时不用每次刷新页面和读取数据库。

  WiZard控件

  WiZard控件非常类似于我们常见的Windows中的向导控件,用于分步骤收集用户提交的数据。

  下面是拖入一个WiZard控件到空白页面的效果:

  和MultiView类似,WiZard是一个WizardStepBase的容器,每个WizardStepBase类似于一个View。与MultiView不同的是,WizardStepBase上显示有上下步骤之间的导航,我们可以控制当前WizardStepBase中的导航样式,这可以通过WizardStepBase的StepType属性来控制。如果进行设置,那么每个WizardStepBase的StepType属性为Auto。下面列出了WizardStepBase的StepType属性的所有可能值:

StepType值 显示行为和结果
WizardStepType.Auto 由声明该WizardStepBase的顺序决定
WizardStepType.Complete 整个步骤最后一步,不显示任何导航按钮
WizardStepType.Finish 收集数据的最后一步,显示“完成”导航按钮
WizardStepType.Start 要显示的第一个步骤,不显示“上一步”导航按钮
WizardStepType.Step 介于第一个和最后一个步骤,显示“上一步”、“下一步”按钮

  在页面中添加一个Wizard控件之后,点击“添加/移除WiZardSteps…”按钮,出现如下界面:

  我们可以设置每一个步骤的Title属性,这个属性是显示每个步骤的名称的。然后再添加每个步骤应该显示的内容。

  下面以代码模拟一个找回密码的功能,前台代码如下:

<%@PageLanguage="C#"AutoEventWireup="true"CodeFile="WiZardDemo.aspx.cs"Inherits="WiZardDemo"%>
<!DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.0Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<htmlxmlns="http://www.w3.org/1999/xhtml">
<headrunat="server">
  <title>WiZard控件用法</title>
</head>
<body>
  <formid="form1"runat="server">
  <div>
    <asp:WizardID="Wizard1"runat="server"ActiveStepIndex="0"Width="400"OnActiveStepChanged="Wizard1_ActiveStepChanged">
      <WizardSteps>
        <asp:WizardSteprunat="server"Title="第一步"StepType="Start">
        <tableborder="0"cellpadding="0"cellspacing="0">
        <tr><td>请输入用户名</td><td><asp:TextBoxrunat="server"ID="txtUserName"></asp:TextBox></td></tr>
        </table>
          <asp:RequiredFieldValidatorID="RequiredFieldValidator1"runat="server"Display="Dynamic"
            ErrorMessage="请输入用户名"ControlToValidate="txtUserName"></asp:RequiredFieldValidator>
        </asp:WizardStep>
        <asp:WizardSteprunat="server"Title="第二步"StepType="Step">
        <tableborder="0"cellpadding="0"cellspacing="0">
        <tr><td>你的密码提示问题</td><td><asp:Labelrunat="server"ID="lbQuestion"></asp:Label></td></tr>
        <tr><td>你的密码提示答案</td><td><asp:TextBoxrunat="server"ID="txtAnswer"></asp:TextBox></td></tr>
        </table>
          <asp:RequiredFieldValidatorID="RequiredFieldValidator2"runat="server"ControlToValidate="txtAnswer"
            ErrorMessage="请输入密码提示答案"></asp:RequiredFieldValidator>
        </asp:WizardStep>
        <asp:WizardSteprunat="server"StepType="Finish"Title="第三步">
        <tableborder="0"cellpadding="0"cellspacing="0">
        <tr><td>请输入新密码</td><td>
          <asp:TextBoxID="txtPassword"runat="server"></asp:TextBox>
        </td></tr>
        <tr><td>请确认新密码</td><td><asp:TextBoxrunat="server"ID="txtCPassword"></asp:TextBox></td></tr>
        </table>
          <asp:RequiredFieldValidatorID="RequiredFieldValidator3"runat="server"ControlToValidate="txtPassword"
            Display="Dynamic"ErrorMessage="请输入新密码"></asp:RequiredFieldValidator>
          <asp:RequiredFieldValidatorID="RequiredFieldValidator4"runat="server"ControlToValidate="txtCPassword"
            Display="Dynamic"ErrorMessage="请确认新密码"></asp:RequiredFieldValidator>
          <asp:CompareValidatorID="CompareValidator1"runat="server"ControlToCompare="txtPassword"
            ControlToValidate="txtCPassword"ErrorMessage="两次密码不一致"></asp:CompareValidator>
        </asp:WizardStep>
        <asp:WizardSteprunat="server"StepType="Complete"Title="第四步">
        恭喜,密码更改成功
        </asp:WizardStep>
      </WizardSteps>
      <HeaderTemplate>
        找回密码
      </HeaderTemplate>
    </asp:Wizard>
  </div>
  </form>
</body>
</html>

  后台代码如下

usingSystem;
usingSystem.Data;
usingSystem.Configuration;
usingSystem.Collections;
usingSystem.Web;
usingSystem.Web.Security;
usingSystem.Web.UI;
usingSystem.Web.UI.WebControls;
usingSystem.Web.UI.WebControls.WebParts;
usingSystem.Web.UI.HtmlControls;
publicpartialclassWiZardDemo:System.Web.UI.Page
{
  protectedvoidPage_Load(objectsender,EventArgse)
  {
  }
  protectedvoidWizard1_ActiveStepChanged(objectsender,EventArgse)
  {
    if(Wizard1.ActiveStepIndex==1)//当用户进入找回密码第二步
    {
      //如果用户输入的是"admin"则提示用户输入"123456"
      if(txtUserName.Text=="admin")
      {
        lbQuestion.Text="请输入123456";
      }
      else//如果用户输入的用户名不是"admin"则跳转到第一步
      {
        Wizard1.ActiveStepIndex=0;
      }
    }
    elseif(Wizard1.ActiveStepIndex==2)//当用户进入找回密码第三步
    {
      if(txtPassword.Text!="123456")
      {
        //用户的找回密码答案正确则修改数据库里的用户登录密码,代码略
      }
      else//如果用户输入的答案不是"123456",则跳转到第二步
      {
        Wizard1.ActiveStepIndex=1;
      }
    }
  }
}

  这个页面的运行效果如下:

  在用户名一栏输入“admin”并点击“下一步”按钮的效果:

  在密码提示答案一栏输入“123456”再点击“下一步”按钮:

  在新密码和确认新密码中都输入“123456”并点击“完成”按钮。

  在上面的例子中没有除了验证控件之外,为了简化流程没有使用任何操作数据库的代码。

  MasterPage母板页

  在我们做Web应用的时候,经常会遇到一些页面之间有很多相同的显示部分和行为,如果每个页面都去重复编写这些代码,那就是一件非常麻烦的事情。因此在asp.net2.0中提出了母板页的概念,我们可以把多个页面之间相同的行为和显示部分放到母板页中,只需要为每个页面编写不同的部分即可,这样如果我们对公共部分需要变化仅仅更改母板页就能达到目的。母板页的文件后缀名为.master,一个网站中允许定义多个母板页。

  母板页不能单独呈现,也就是我们不能在浏览器中直接输入母板页的url地址进行访问,必须依赖于内容页才能呈现。

  下面是新建一个母板页的源代码:

<%@MasterLanguage="C#"AutoEventWireup="true"CodeFile="FrontPage.master.cs"Inherits="FrontPage"%>
<!DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.0Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<htmlxmlns="http://www.w3.org/1999/xhtml">
<headrunat="server">
  <title>无标题页</title>
</head>
<body>
  <formid="form1"runat="server">
  <div>
    <asp:contentplaceholderid="ContentPlaceHolder1"runat="server">
    </asp:contentplaceholder>
  </div>
  </form>
</body>
</html>

  在母板页中有一个“<asp:contentplaceholder></asp:contentplaceholder>”标记,这相当于一个占位标记,将来使用了这个母板页的内容页中的内容将在这个标记中显示。因为母板页已经包含了<html><head></head><form runat=”server”></form></html>标记,所以内容页中不允许再出现这些标记。

  新建一个使用使用当前使用母板页的内容页步骤如下:

  (1)在网站项目或者网站项目下的文件夹上点鼠标右键,在出现的右键菜单中选择“添加新项”,出现如下界面:

  注意:一定要勾选“选择母板页”选项。

  (2)点击“添加”按钮,这时会出现选择母板页的界面,如下图:

  (3)选择正确的母板页,然后点“确定”按钮,这样就完成了添加一个内容页。

  这时内容页的代码如下:

<%@PageLanguage="C#"MasterPageFile="~/FrontPage.master"AutoEventWireup="true"CodeFile="MyPage.aspx.cs"Inherits="MyPage"Title="UntitledPage"%>
<asp:ContentID="Content1"ContentPlaceHolderID="ContentPlaceHolder1"Runat="Server">
</asp:Content>

  在内容页中有一个<asp:Content></asp:Content>标记,只有放在这个标记之间的代码将来运行时才会可见。

  内容页有几个常见属性如下表所示:

属性名 说明
Master 获取当前内容页所使用的母板页(如果有的话)
MasterPageFile 内容所使用的母板页文件的位置
Title 内容页的标题
有时候需要访问母板页中的控件,比如母板页上有一个Label控件用于显示当前服务器时间,可以通过获取当前内容页的Master属性来获取所使用的母板页,然后利用母板页的FindControl(string controlId)方法来根据控件的ID查找母板页的控件。

  下面是一个内容页访问母板页的例子。

  母板页的代码:

<%@MasterLanguage="C#"AutoEventWireup="true"CodeFile="FrontPage.master.cs"Inherits="FrontPage"%>
<!DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.0Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<htmlxmlns="http://www.w3.org/1999/xhtml">
<headrunat="server">
  <title>无标题页</title>
</head>
<body>
  <formid="form1"runat="server">
  <div>
  <table><tr><td>
    服务器时间:<asp:LabelID="lbServerTime"runat="server"Text=""></asp:Label></td></tr>
  <tr><td>
    <asp:contentplaceholderid="ContentPlaceHolder1"runat="server">
    </asp:contentplaceholder>
    </td></tr>
    <tr><td>
      版本号:<asp:LabelID="lbCopyRight"runat="server"Text=""></asp:Label></td></tr>
    </table>
  </div>
  </form>
</body>
</html>

  内容页的前台代码:

<%@PageLanguage="C#"MasterPageFile="~/FrontPage.master"AutoEventWireup="true"CodeFile="MyPage.aspx.cs"Inherits="MyPage"Title="内容页访问母板页控件的例子"%>
<asp:ContentID="Content1"ContentPlaceHolderID="ContentPlaceHolder1"Runat="Server">
内容页的内容放在这里
</asp:Content>

  内容页的后台代码:

usingSystem;
usingSystem.Data;
usingSystem.Configuration;
usingSystem.Collections;
usingSystem.Web;
usingSystem.Web.Security;
usingSystem.Web.UI;
usingSystem.Web.UI.WebControls;
usingSystem.Web.UI.WebControls.WebParts;
usingSystem.Web.UI.HtmlControls;
publicpartialclassMyPage:System.Web.UI.Page
{
  protectedvoidPage_Load(objectsender,EventArgse)
  {
    //其中lbServerTime是母板页上的控件的ID
    LabellbTimer=(Label)(this.Master.FindControl("lbServerTime"));
    lbTimer.Text=DateTime.Now.ToString("yyyy-MM-dd");
    LabellbCopyRight=(Label)(this.Master.FindControl("lbCopyRight"));
    lbCopyRight.Text="Version1.0";
  }
}

  页面的运行效果:

  母板页的动态替换

  在编程开发中还可以根据条件动态替换内容页所使用的母板页,母板页替换处理要在内容的初始化阶段,也就是在内容页的PreInit事件里。

  下面就是一个随即动态替换母板页的例子:

usingSystem;
usingSystem.Data;
usingSystem.Configuration;
usingSystem.Collections;
usingSystem.Web;
usingSystem.Web.Security;
usingSystem.Web.UI;
usingSystem.Web.UI.WebControls;
usingSystem.Web.UI.WebControls.WebParts;
usingSystem.Web.UI.HtmlControls;
publicpartialclassMyPage:System.Web.UI.Page
{
  //在这里更换母板页,不能在Page_Load事件里更换,会报异常
  protectedoverridevoidOnPreInit(EventArgse)
  {
    if(DateTime.Now.Millisecond%2==0)
    {
      //注意"~/MasterPage.master"母板页中必须有当前母板页中一致的控件
      this.MasterPageFile="~/MasterPage.master";
    }
    base.OnInit(e);
  }
}

  总结:本篇讲述了一些比较复杂的网页效果的实现办法,比如类似于WinForm中的选项卡式效果、树形菜单、用于多步骤收集用户信息的向导效果等,还有便于网站统一布局合显示的母板页的使用,并且讲述了如何动态替换母板页。下一篇将讲述web.config的用法和配置。

  后记:最近有不少朋友在我的博客http://blog.csdn.net/zhoufoxcn上留言,要求在我原有计划上增加一些新的内容,我会酌情增加一些,但是由于时间不会一一照顾到,敬请谅解


« 
» 
快速导航

Copyright © 2016 phpStudy | 豫ICP备2021030365号-3