从ASP.net中的用户控件访问页面上的文本框

时间:2013-03-07 15:45:01

标签: c# asp.net user-controls

我有一些页面略有不同,但都有相同的“操作按钮”,每个页面执行相同的任务。我没有复制代码,而是创建了一个用户控件,其中包含执行操作的按钮 - 但是我似乎无法执行一项操作。

每个页面都有一个文本框(不在用户控件中,因为它位于页面的不同位置)。当我单击“保存注释”按钮(位于用户控件中)时,我似乎无法访问文本框中的文本。

我尝试过这样的事情:

TextBox txtComments = (TextBox)this.Parent.FindControl("txtComments");
SaveChanges(txtComments.Text);

...但是txtComments返回为null。

所以,我想知道这是否可行,或者是否有更好的方法来做我想做的事情?

修改:文本框位于原始页面的占位符中...

编辑2:发布缩小的解决方案 - 仍然无法解决这个问题。

修改3 :删除解决方案以节省空间 - 解决了问题。

4 个答案:

答案 0 :(得分:7)

我的解决方案最终变得非常简单......

TextBox txt = this.Parent.Parent.FindControl("ContentPlaceHolder2").FindControl("TextBox1") as TextBox;
if (txt != null) Label1.Text = txt.Text;

之前我出错的地方是我使用了错误的ContentPlaceHolder ID。我在页面中使用了占位符的ID,而不是母版页中的ID。

答案 1 :(得分:1)

使用Page公开的WebControl属性,这是服务器端控件的公共基础。

您甚至可以将实例强制转换为特定页面类型并直接访问控件(如果范围允许),而不是使用FindControl

答案 2 :(得分:1)

回顾一下情况 - 你需要在子控件的页面上对控件进行FindControl,但是 -

  1. 您的项目有MasterPage,在这种情况下this.Page似乎不起作用,我们使用this.Parent代替
  2. 你的“目标”控件位于PlaceHolder中,它本身位于ContentPlaceHolder中,所以它不像this.Parent.FindControl()
  3. 那么简单
  4. 您的孩子ASCX控件试图找到“目标”控件,在本例中是一个文本框,实际上是在另一个ContentPlaceHolder中,所以再次,this.Parent.Parent或其他什么都不起作用。
  5. 由于您在我的初始this.Parent回答后提到有关控件在彼此不同的ContentPlaceHolder中以及在另一个子控件中,因此它会使您的查询复杂化。

    根据这些标准,以及你至少知道包含(在其中的某个地方)你的目标TextBox的contentPlaceHolder控件的事实,这里有一些我在新的ASP.net Web窗体应用程序中编写的代码:

    以递归方式检查传递给它的ContentPlaceHolder的控件集合,并找到您的控件。

    只需传递ControlID和ContentPlaceHolderID,就会以递归方式找到它。

    此代码替换下面我原来的代码,位于ChildControl.ascx.cs文件中的相同项目:

    使用System; 使用System.Web.UI; 使用System.Web.UI.WebControls; 使用System.Linq; 使用System.Collections.Generic;

    namespace FindControlTest
    {
        public partial class ChildControl : System.Web.UI.UserControl
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                var textBoxTest = FindControlInContentPlaceHolder("TextBoxTest", "FeaturedContent") as TextBox;
    
                Response.Write(textBoxTest.Text);
                Response.End();
            }
    
            private Control FindControlInContentPlaceHolder(string controlID, string contentPlaceHolderID)
            {
                if (null == this.Page ||
                    null == this.Page.Master)
                {
                    return null;
                }
    
                var contentPlaceHolder = this.Page.Master.FindControl(contentPlaceHolderID);
                var control = getChildControl(controlID, contentPlaceHolder);
                return control;
            }
    
            private Control getChildControl(string controlID, Control currentControl)
            {
                if (currentControl.HasControls())
                {
                    foreach(Control childControl in currentControl.Controls)
                    {
                        var foundControl = childControl.FindControl(controlID);
                        if (null != foundControl)
                        {
                            return foundControl;
                        }
                        else
                        {
                            return getChildControl(controlID, childControl);
                        }
                    }
                }
    
                return null;
            }
        }
    }
    

    注意:

    我在几个事件中尝试了这个,甚至在Init()上我能够获得TextBox值 如果您看到null,则可能是由于传递了错误的ID或我尚未遇到的情况。如果您使用其他信息编辑您的问题(因为有很多信息)并显示哪个变量为null,则可以解析它。

    请注意,我在MasterPage中添加了一些复杂性,例如Panel中的PlaceHolder,然后将ContentPlaceHolder放在那里,代码仍然有效。我甚至编译.net 4.5,4.0,3.5和3.0思考也许FindControl与MasterPages的工作方式不同,但它仍然适用于每次。如果仍然得到null,则可能需要发布一些额外的MarkUp。

    测试项目的其余部分

    页面(基于默认的MasterPage)

    <%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="FindControlTest._Default" %>
    <%@ Register TagName="ChildControl" TagPrefix="uc1" Src="~/ChildControl.ascx" %>
    
    <asp:Content runat="server" ContentPlaceHolderID="FeaturedContent">
    
        <asp:PlaceHolder ID="PlaceHolderTest" runat="server">
            <asp:TextBox ID="TextBoxTest" Text="Hello!" runat="server"/>
        </asp:PlaceHolder>
    
    </asp:Content>
    <asp:Content ContentPlaceHolderID="MainContent" runat="server">
    
        <uc1:ChildControl id="ChildControlTest" runat="server" />
    
    </asp:Content>
    

    我添加了一个名为ChildControl.ascx的控件,其中只包含此内容:

    <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="ChildControl.ascx.cs" Inherits="FindControlTest.ChildControl" %>
    Hello child!
    

    结果是“你好!”在页面上。

答案 3 :(得分:0)

如果要将代码隐藏中的textbox属性作为intellisence属性访问,只需将其设置为用户控件中的字符串属性即可。

1. In the user control, create a public string property that returns textbox string value..

public string MyText
{
get
{
return txt1.Text;
}
}

2. Register the user control on the page

<%@ Register TagPrefix="uc" TagName="MyControl" Src="~/mycontrol.ascx" />

and declare it..

<uc:MyControl ID="control1" runat="server" />

3. From the codebehind now you can read the property..

Response.Write(control1.MyText);

Hope it helps

Thanks...