Доступ к текстовому поле на странице из пользовательского элемента управления в ASP.net

У меня есть несколько страниц, которые немного отличаются, но у всех есть те же "кнопки действий", которые выполняют одни и те же задачи для каждой страницы. Вместо того, чтобы дублировать код, я создал пользовательский элемент управления, который включает в себя кнопки, которые выполняют действия, - но есть одно действие, которое я не могу сделать.

Каждая страница имеет текстовое поле (которое не находится внутри пользовательского элемента управления, так как оно находится в другом месте страницы). Когда я нажимаю кнопку "Сохранить комментарий" (которая находится внутри пользовательского элемента управления), я не могу получить доступ к тексту в текстовом поле.

Я пробовал использовать что-то вроде этого:

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

... но txtComments возвращается как null.

Итак, мне интересно, возможно ли это, или, может быть, если есть лучший способ сделать то, что я пытаюсь сделать?

Изменить: Текстовое поле находится в Заполнитель на исходной странице...

Изменить 2: Опубликовать мини-решение - все равно не может понять, что это значит.

Изменить 3: Удалено решение для сохранения пространства - разрешена проблема.

Ответ 1

Мое решение оказалось неожиданно простым.

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

Когда я ошибался раньше, я использовал неправильный идентификатор ContentPlaceHolder. Я использовал идентификатор заполнителя на странице, а не идентификатор с главной страницы.

Ответ 2

Используйте свойство Page, выставленное WebControl, общая база элементов управления на стороне сервера.

Вы могли бы даже затем привести экземпляр к определенному типу страницы и напрямую обращаться к элементу управления (если позволяет область), вместо использования FindControl.

Ответ 3

Чтобы повторить ситуацию - вам нужно сделать FindControl элемента управления на странице из дочернего элемента управления, однако -

  • В вашем проекте есть MasterPage, и в этом случае this.Page, похоже, не работает, и вместо этого мы используем this.Parent
  • Ваш "целевой" элемент управления находится внутри PlaceHolder, который сам находится внутри ContentPlaceHolder, поэтому он не так прост, как просто this.Parent.FindControl()
  • Ваш дочерний элемент управления ASCX, пытающийся найти "целевой" элемент управления, в этом случае текстовое поле, фактически находится в ДРУГОЙ ContentPlaceHolder, так что снова этот. Parent.Parent или что-то не будет работать.

Поскольку вы упомянули после моего первоначального ответа this.Parent о том, что элементы управления находятся в другом ContentPlaceHolder друг от друга, а в другом дочернем элементе управления это немного усложняет ваш запрос.

Исходя из этих критериев и того факта, что вы, по крайней мере, знаете элемент управления contentPlaceHolder, который содержит (где-то внутри него) ваш целевой TextBox, вот какой-то код, который я написал, который работает для меня в новом приложении ASP.NET Web Forms:

Он рекурсивно проверяет коллекцию элементов управления 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, ее можно решить.

Обратите внимание, что я добавил некоторую сложность моему MasterPage, например PlaceHolder внутри Panel, а затем разместил 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!

Результат: "Привет!" на странице.