状況を要約すると、子コントロールからページ上のコントロールのFindControlを実行する必要がありますが、
- プロジェクトにMasterPageがありますが、この場合
this.Page
は機能しないようです。this.Parent
代わり に使用します
- 「ターゲット」コントロールはPlaceHolder内にあり、PlaceHolder自体はContentPlaceHolder内にあるため、単純ではありません。
this.Parent.FindControl()
- 「ターゲット」コントロール(この場合はテキストボックス)を見つけようとしている子ASCXコントロールは、実際には別のContentPlaceHolderにあるため、this.Parent.Parentなどは機能しません。
this.Parent
コントロールが互いに異なるContentPlaceHolderにあり、別の子コントロールにあることについての私の最初の回答の後で言及したので、クエリが少し複雑になります。
これらの基準と、ターゲットTextBoxを(その内部のどこかに)含むcontentPlaceHolderコントロールを少なくとも知っているという事実に基づいて、新しいASP.netWebフォームアプリケーションで機能するコードを次に示します。
渡された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が渡されたか、まだ発生していない状況が原因である可能性があります。追加情報を使用して質問を編集し(多くの情報が含まれているため)、どの変数がnullであるかを示すと、解決できます。
パネル内のPlaceHolderなど、MasterPageに複雑さを追加し、そこに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!
結果は「こんにちは!」です。ページ上。