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

时间:2022-10-19 22:23:16

I have a some pages that are slightly different, but all have the same "action buttons" that do the same tasks for each page. Instead of duplicating the code, I made a user control that includes buttons that perform actions - but there's one action I can't seem to do.

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

Each page has a textbox (that's not inside the user control, as it's in a different location of the page). When I click the "Save comment" button (that is within the User Control), I can't seem to access the text in the Textbox.

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

I have tried using something like this:

我试过用这样的东西:

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

...but txtComments comes back as null.

...但是txtComments返回null。

So, I'm wondering if this is possible, or perhaps if there's a better way to do what I'm trying to do?

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

Edit: The Textbox is in a Placeholder on the original page...

编辑:文本框位于原始页面的占位符中...

Edit 2: Posting minified solution - still can't figure this one out.

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

Edit 3: Removed solution to conserve space - resolved the issue.

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

4 个解决方案

#1


7  

My solution ended up being surprisingly simple....

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

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

Where I was going wrong before was that I was using the wrong ContentPlaceHolder ID. I was using the ID of the placeholder in the page, rather than the ID from the Master Page.

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

#2


1  

Use the Page property exposed by WebControl, the common base of server-side controls.

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

You could even then cast the instance to the specific page type and access the control directly (if scope allows), instead of using FindControl.

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

#3


1  

To recap the situation - you need to do a FindControl of a control on a page from a child control, however -

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

  1. Your project has a MasterPage, in which case this.Page seems to not work, and we use this.Parent instead
  2. 你的项目有一个MasterPage,在这种情况下this.Page似乎不起作用,我们使用this.Parent代替
  3. Your "target" control is inside a PlaceHolder, which itself is inside a ContentPlaceHolder, so it's not as simple as just this.Parent.FindControl()
  4. 你的“目标”控件位于PlaceHolder中,它本身位于ContentPlaceHolder中,因此它不像this.Parent.FindControl()那么简单。
  5. Your child ASCX control that is trying to find the "target" control, in this case a textbox, is actually in ANOTHER ContentPlaceHolder, so again, this.Parent.Parent or whatever will not work.
  6. 你的孩子ASCX控件试图找到“目标”控件,在这种情况下是一个文本框,实际上是在另一个ContentPlaceHolder中,所以再次,this.Parent.Parent或其他什么都行不通。

Since you mentioned after my initial this.Parent answer about the controls being in a different ContentPlaceHolder from each other, and in another child control, it complicates your query a bit.

因为你在我最初的this.Parent答案之后提到了控件在不同的ContentPlaceHolder中,并且在另一个子控件中,它使你的查询复杂化了一些。

Based on these criteria, and the fact that you at least know the contentPlaceHolder control which contains (somewhere inside of it) your target TextBox, here's some code I wrote that works for me in a new ASP.net Web Forms application:

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

It recursively checks controls collection of the ContentPlaceHolder you pass to it, and finds your control.

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

Just pass the ControlID and ContentPlaceHolderID, and it will recursively find it.

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

This code is a replacement for my original one below with the same project, located inside of ChildControl.ascx.cs file:

这段代码替换了我原来的一个项目,位于ChildControl.ascx.cs文件中:

using System; using System.Web.UI; using System.Web.UI.WebControls; using System.Linq; using System.Collections.Generic;

使用系统;使用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;
        }
    }
}

Note:

注意:

I tried this in a few events and even on Init() I was able to get the TextBox value If you are seeing a null it is likely due to an incorrect ID being passed or a situation I didn't encounter yet. If you edit your question with additional info (as there has been a lot of it) and show what variable is null, it can be resolved.

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

Note that I added some complexity to my MasterPage, such as a PlaceHolder inside a Panel, and then put the ContentPlaceHolder in there, and the code still works. I even compiled for .net 4.5, 4.0, 3.5, and 3.0 thinking maybe FindControl works differently with MasterPages, but still it works every time. You may need to post some additional MarkUp if you still get a null.

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

The Rest of the Test Project

其余的测试项目

The Page (based on default MasterPage)

页面(基于默认的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>

I added a control called ChildControl.ascx that only has this in it:

我添加了一个名为ChildControl.ascx的控件,其中只有这个:

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

The result is "Hello!" on the page.

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

#4


0  

If you want to access the textbox property in codebehind as intellisence property, simply make it a string property in the user control.

如果要将代码隐藏中的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...

#1


7  

My solution ended up being surprisingly simple....

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

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

Where I was going wrong before was that I was using the wrong ContentPlaceHolder ID. I was using the ID of the placeholder in the page, rather than the ID from the Master Page.

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

#2


1  

Use the Page property exposed by WebControl, the common base of server-side controls.

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

You could even then cast the instance to the specific page type and access the control directly (if scope allows), instead of using FindControl.

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

#3


1  

To recap the situation - you need to do a FindControl of a control on a page from a child control, however -

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

  1. Your project has a MasterPage, in which case this.Page seems to not work, and we use this.Parent instead
  2. 你的项目有一个MasterPage,在这种情况下this.Page似乎不起作用,我们使用this.Parent代替
  3. Your "target" control is inside a PlaceHolder, which itself is inside a ContentPlaceHolder, so it's not as simple as just this.Parent.FindControl()
  4. 你的“目标”控件位于PlaceHolder中,它本身位于ContentPlaceHolder中,因此它不像this.Parent.FindControl()那么简单。
  5. Your child ASCX control that is trying to find the "target" control, in this case a textbox, is actually in ANOTHER ContentPlaceHolder, so again, this.Parent.Parent or whatever will not work.
  6. 你的孩子ASCX控件试图找到“目标”控件,在这种情况下是一个文本框,实际上是在另一个ContentPlaceHolder中,所以再次,this.Parent.Parent或其他什么都行不通。

Since you mentioned after my initial this.Parent answer about the controls being in a different ContentPlaceHolder from each other, and in another child control, it complicates your query a bit.

因为你在我最初的this.Parent答案之后提到了控件在不同的ContentPlaceHolder中,并且在另一个子控件中,它使你的查询复杂化了一些。

Based on these criteria, and the fact that you at least know the contentPlaceHolder control which contains (somewhere inside of it) your target TextBox, here's some code I wrote that works for me in a new ASP.net Web Forms application:

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

It recursively checks controls collection of the ContentPlaceHolder you pass to it, and finds your control.

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

Just pass the ControlID and ContentPlaceHolderID, and it will recursively find it.

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

This code is a replacement for my original one below with the same project, located inside of ChildControl.ascx.cs file:

这段代码替换了我原来的一个项目,位于ChildControl.ascx.cs文件中:

using System; using System.Web.UI; using System.Web.UI.WebControls; using System.Linq; using System.Collections.Generic;

使用系统;使用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;
        }
    }
}

Note:

注意:

I tried this in a few events and even on Init() I was able to get the TextBox value If you are seeing a null it is likely due to an incorrect ID being passed or a situation I didn't encounter yet. If you edit your question with additional info (as there has been a lot of it) and show what variable is null, it can be resolved.

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

Note that I added some complexity to my MasterPage, such as a PlaceHolder inside a Panel, and then put the ContentPlaceHolder in there, and the code still works. I even compiled for .net 4.5, 4.0, 3.5, and 3.0 thinking maybe FindControl works differently with MasterPages, but still it works every time. You may need to post some additional MarkUp if you still get a null.

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

The Rest of the Test Project

其余的测试项目

The Page (based on default MasterPage)

页面(基于默认的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>

I added a control called ChildControl.ascx that only has this in it:

我添加了一个名为ChildControl.ascx的控件,其中只有这个:

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

The result is "Hello!" on the page.

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

#4


0  

If you want to access the textbox property in codebehind as intellisence property, simply make it a string property in the user control.

如果要将代码隐藏中的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...