zoukankan      html  css  js  c++  java
  • 在母版页里使用FindControl的困惑


     

    在母版里使用FindControl

       通常在内容页里会使用不止一个Content控件,在这种情况下. 我们可能需要让不同Content的里的控件进行通信,本节就来介绍这些问题。

    例如下面是一个简单的母版simple.master

    <%@ Master Language="C#" AutoEventWireup="true" CodeFile="simple.master.cs" Inherits="simple" %>

     

    <!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>Untitled Page</title>

    </head>

    <body>

        <form id="form1" runat="server">

        <div>

            <asp:contentplaceholder id="ContentUp" runat="server">

            </asp:contentplaceholder>

               <asp:contentplaceholder id="ContentDown" runat="server">

            </asp:contentplaceholder>

        </div>

        </form>

    </body>

    </html>

     

    在这个母版里使用了两个ContentPlageHolder控件,其ID分别为ContentUpContentDown,这里的名称表示将来我想将内容页分为上半部和下半部。

     

    为了使用该母版,我建立了一个 内容页 FindControl_Masterpage.aspx,代码如下:

    <%@ Page Language="C#"  Trace="true" MasterPageFile="~/simple.master" AutoEventWireup="true" CodeFile="FindControl_Masterpage.aspx.cs" Inherits="FindControl_Masterpage" Title="Untitled Page" %>

    <asp:Content ID="Content1" ContentPlaceHolderID="ContentUp" Runat="Server">

    <asp:Label runat="server" ID="lblInfo"></asp:Label>

    </asp:Content>

    <asp:Content ID="Content2" ContentPlaceHolderID="ContentDown" Runat="Server">

    <asp:TextBox ID="txtInfo" runat="server"></asp:TextBox>

    <asp:Button ID="btnSubmit" runat="server" Text="Submit" OnClick="btnSubmit_Click" ></asp:Button>

    </asp:Content>

     

      这里的内容页很简单,在ContentUp里放置了一个IDlblInfo的标签,在ContentDown里放置了一个IDtxtInfo的文本框和IDbtnSubmit的按钮。

    现在我想在文本框里输入文本,然后单击按钮,让Label标签显示输入的文本,所以在btnSubmit_Click的事件里输入代码如下:

    protected void btnSubmit_Click(object sender, EventArgs e)

        {

          lblInfo.Text = txtInfo.Text;

         }

     上面的方法在内容页运行时工作的很好,但是有时候我们的要求可能并不是这么简单。比方说,我在Content1中定义有一个ObjectDataSource,在Content2中定义有一个TextBox,我想将ObjectDataSourceSelectParameter设定到TextBox上,那么此时就需要获取TextBox控件。您可能很容易编写如下代码:

    protected void btnSubmit_Click(object sender, EventArgs e)

        {

        Label lblLabel = (Label)Page.FindControl("lblInfo");

          lblLabel.Text = txtInfo.Text;

         }

      我么的想法是利用PageFindControl控件查扎IDlblInfo的标签,然后设置其Text属性。然而很遗憾,如果您使用上面代码,在运行时将出现如下的提示错误: 

     

    image1.png 

     

      也许有人认为这是因为LabelButton控件在不同的Content所致,但是虽然TextBoxButton在同一个Content,那么你编写如下代码同样会出现上面的问题:

    protected void btnSubmit_Click(object sender, EventArgs e)

        {

       TextBox txtTextBox = (TextBox)Page.FindControl("txtInfo");

            txtTextBox.Text = "helloworld";

         }

      那么为什么会出现上面错误呢?前面介绍了母版页和内容页运行原理时曾经说过,用户最终请求的是内容页,母版页和内容页在之中处理请求时,母版页会融合到内容页里,我们可以利用跟踪技术查看这种结果,此时在内容页里添加Trace属性如下:

    <%@ Page Language="C#"  Trace="true" … …%>

      这样在运行FindControl_MasterPage.aspx时,我们可以看到下面的跟踪效果

     

     

    image003.png 

     

    从图中可以看到,在页面Page控件树中,ContentUpContentDown直接在Page的控件树下,而LabelTextBoxButton又分别在ContentUpContentDown下,那么为什么FindControl找不到LabelTextBoxButton呢?

     这时,我们需要重新查看一下FindControl的定义,MSDN给出的解释如下:在页命名容器中搜索带指定标识符的服务器控件,但是请注意其备注的说明:

    FindControl 方法只搜索页的直接或顶级容器;它不在页所包含的命名容器中递归搜索控件。

    也就是FindControl可以找到ContentUpContentDown但是找不到LabelTextButton。如果更显示的表示如下图

    FindControl不会在ContentUp/ContentDown查找其子控件,这就是为什么会出现上面错误的原因。

     

     

    image005.png 

    当然,这里的讨论并不完全准确,如果您仔细查看页面跟踪结果可以发现ContentUpContentDown应该算是aspnetForm的子控件,但是为什么它就可以查找aspnetForm下的子控件呢?

    这里设计到控件的定义,事实上FindControl只查找未实现INamingContainer 接口的控件。而aspnetForm则未实现InamingContainer接口,就是这个原因。(判断一个控件是否实现InamingContainer接口简单的说就是在页面上能否重复使用,例如TextBox实现了InamingContainer结果,那么在一个Web页面上如下的代码是正确的

    <asp:TextBox ID="Textbox1" runat="server"></asp:TextBox>

    <asp:TextBox ID=" Textbox2" runat="server"></asp:TextBox>

    Form未实现,所以如果你在一个Web页面上同时使用了两个Form控件,如下

    <form id="form1" runat="server"></form>

    <form id="form2" runat="server"></form>

    则这种写法是错误的。

     

    既然FindControl可以在控件内部嵌套搜索,所以我们就很容易获取TextBoxLabelButton,如下:

    获取

      protected void btnSubmit_Click(object sender, EventArgs e)

        {

            ContentPlaceHolder cphUp;

            Label lblLabel;

            cphUp = (ContentPlaceHolder)Master.FindControl("ContentUp");

            lblLabel = (Label)cphUp.FindControl("lblInfo");

            ContentPlaceHolder cphDown;

            cphDown=(ContentPlaceHolder)Master.FindControl("ContentDown");

            TextBox txtTextBox;

            Button btnButton;

            txtTextBox = (TextBox)cphDown.FindControl("txtInfo");

            if (cphUp != null && cphDown!=null)

            {

              if (lblLabel != null && txtTextBox != null)

                    lblLabel.Text = txtTextBox.Text;

            }

         

        }

    这样就可以实现在内容页上获取控件通信了。

    image007.png

  • 相关阅读:
    【C++标准库】C++11新特性
    使用线程池
    Halcon相机硬触发采集图片
    C#之线程同步
    多线程之异常处理
    java基础 Arrays
    java基础 static关键字
    java基础 String
    c# 更新web.config
    java 基础
  • 原文地址:https://www.cnblogs.com/mqingqing123/p/432430.html
Copyright © 2011-2022 走看看