Доступ к текстовому поле на странице из пользовательского элемента управления в 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!
Результат: "Привет!" на странице.