【问题标题】:Access Textbox on Page from User Control in ASP.net从 ASP.net 中的用户控件访问页面上的文本框
【发布时间】:2013-03-07 15:45:01
【问题描述】:

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

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

我尝试过使用这样的东西:

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

...但是 txtComments 返回为空。

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

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

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

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

【问题讨论】:

  • 抱歉提醒您,您是否将正确的 TextBox ID 传递给 FindControl(...)?否则,当我处理保存按钮所在的 UserControl 的代码隐藏内的按钮单击事件时,这对我来说也可以正常工作,而 TextBox 则保留在主页上。
  • 我已经检查了很多次了!文本框在 PlaceHolder 控件中是否重要(显示/隐藏它和其他项目的可见性)?
  • 附带说明,如果您的页面上有一个 CheckBoxList 并且 FindControl 命中它,它将始终返回 null。
  • @BlueChameleon - 在什么版本的 .net 中?我正在运行一个 4.5 应用程序,FindControl() 对 CheckBoxList 没有问题,仅供参考;它没有返回 null。
  • 对不起,我没有写对。它应该说当 FindControl 命中 CheckBoxList 时,CheckBoxList 总是返回自身。为了适应这种情况,您必须确保 FindControl 返回的控件具有您要查找的 ID。更多信息在这里:weblogs.aspnet05.orcsweb.com/scottcate/archive/2005/08/04/…

标签: c# asp.net user-controls


【解决方案1】:

我的解决方案最终出乎意料地简单......

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 你能澄清一下吗?我之前尝试过 Page.FindControl 没有成功...
    • 我了解如何使用 Page.FindControl,但由于某种原因,找不到我的文本框 - 我不确定为什么。
    • 文本框是直接在页面上,还是在面板之类的其他控件中? FindControl 不是递归的,因此 Page.FindControl() 不会找到在另一个控件中声明的控件,而不是直接在页面上。
    • 所以我添加了一个 Page.FindControl("placeholderID") 来查找占位符 - 但即使这样也返回 null...
    【解决方案3】:

    回顾一下情况 - 但是,您需要从子控件对页面上的控件执行 FindControl -

    1. 您的项目有一个 MasterPage,在这种情况下,this.Page 似乎不起作用,我们改用this.Parent
    2. 您的“目标”控件位于 PlaceHolder 中,而 PlaceHolder 本身位于 ContentPlaceHolder 中,因此它不像 this.Parent.FindControl() 那样简单
    3. 您尝试查找“目标”控件的子 ASCX 控件(在本例中为文本框)实际上位于另一个 ContentPlaceHolder 中,因此 this.Parent.Parent 或其他任何内容都不起作用。

    由于您在我最初的 this.Parent 回答后提到控件彼此位于不同的 ContentPlaceHolder 中,并且在另一个子控件中,因此您的查询有点复杂。

    基于这些标准,以及您至少知道包含(其中某处)您的目标 TextBox 的 contentPlaceHolder 控件这一事实,下面是我编写的一些代码,适用于新的 ASP.net Web 窗体应用程序:

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

    只需传递ControlID和ContentPlaceHolderID,它就会递归查找。

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

    使用系统; 使用 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 或我尚未遇到的情况。如果您使用附加信息(因为已经有很多)编辑您的问题并显示什么变量为空,则可以解决。

    请注意,我在 MasterPage 中添加了一些复杂性,例如 Panel 中的 PlaceHolder,然后将 ContentPlaceHolder 放入其中,代码仍然有效。我什至为 .net 4.5、4.0、3.5 和 3.0 进行了编译,我认为 FindControl 与 MasterPages 的工作方式可能不同,但它仍然每次都能工作。如果您仍然得到空值,您可能需要发布一些额外的标记。

    测试项目的其余部分

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

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

    【讨论】:

    • 这绝对是有道理的......通过使用调试,我越来越接近......但是另一个障碍?我的用户控件和文本框位于页面的不同 ContentPlaceHolders 中(是的,我正在使用母版页)。将尝试使用这种技术深入一个元素...
    • 这让事情变得更加棘手,我将很快更新我的答案,让您可以从任何 ContentPlaceHolder 中找到控件。
    • @MetalAdam 我更新了这个答案,如果您传递控件 ID 和 ContentPlaceHolderID,则递归查找控件,这应该适用于您的情况。
    • 对于这一行 - var contentPlaceHolder = this.Page.Master.FindControl(contentPlaceHolderID); - 我不断得到一个 null 返回的值。我已经三次检查了 ID,但仍然无法正常工作...
    • @MetalAdam 您需要将实际的 contentplaceholderID 传递给函数,您传递的是什么值以及包含您的 TextBox 的 ContentPlaceHolder 的 ContentPlaceholderID(不是 ID)是什么?
    【解决方案4】:

    如果您想将代码隐藏中的文本框属性作为智能属性访问,只需将其设置为用户控件中的字符串属性即可。

    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...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-11-09
      • 1970-01-01
      • 2011-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多