by WebSurfer
2015年10月24日 14:18
ユーザーコントロール(.ascx)の中に配置した子コントロールの ClientID を、そのユーザーコントロールを使う .aspx ページで取得するにはどうしたらいいかという話を書きます。
上の画像は、ユーザーコントロール(子に TextBox を持つ)の html ソースがブラウザにレンダリングされた後、クライアント側でその TextBox(html では input 要素)を JavaScript の getElementById メソッドで取得し、input 要素の change イベントにリスナをアタッチして入力された値を取得して alert で表示したものです。(ブラウザは Chrome です)
input 要素 <input type="text" id="xxx" ... /> を getElementById メソッドで取得するためには id の値 xxx が必要です。サーバー側のコードでは ClientID が xxx になりますので TextBox.Client プロパティで容易に取得できますが、クライアント側ではどのようにするのでしょうか?
一旦 html ソースをレンダリングし、その中の xxx を調べてそれを JavaScript のコードにハードコーディングする・・・というのは避けた方がよさそうです。将来 ClientID の命名規則が変わると動かなくなりますし、コードの可読性もよくないので保守の問題もありそうです。
なので、getElementById("<%=TextBox.ClientID%>") のようにコードブロック(即ち、<% ... %>)で取得するのがよさそうですが、TextBox はユーザーコントロールの中の子コントロールとして配置されているのでそうはいきません。
いろいろ解決法はあると思いますが、ユーザーコントロールのコードビハインドに TextBox の ClientID を取得するためのパブリックプロパティを追加し、.aspx ページではそのパブリックプロパティをコードブロックで埋め込んでやればいいはずです。
ユーザーコントロール(.ascx)
ユーザーコントロール(.ascx)のコードは具体的には以下のようになります。本題とは関係ないコードがいろいろと入っていますが、TextBoxClientID プロパティの定義に注目してください。
<%@ Control Language="C#"
ClassName="_0014_ClientIDInWebUserControl" %>
<%@ Register Assembly="AjaxControlToolkit"
Namespace="AjaxControlToolkit"
TagPrefix="Ajax" %>
<script runat="server">
public string TextBoxClientID
{
get { return Control_Date.ClientID; }
}
</script>
<asp:TextBox ID="Control_Date"
runat="server"
Width="130px"
MaxLength="1"
CssClass="imeDisabled"
style="text-align:justify"
autocomplete="on"
ValidationGroup="MKE" />
<Ajax:MaskedEditExtender
ID="Control_DateMaskEditExtender"
runat="server"
TargetControlID="Control_Date"
Mask="9999/99/99"
MessageValidatorTip="true"
OnFocusCssClass="MaskedEditFocus"
OnInvalidCssClass="MaskedEditError"
MaskType="Date"
DisplayMoney="Left"
AcceptNegative="Left"
ErrorTooltipEnabled="True" />
<Ajax:MaskedEditValidator
ID="Control_DateMaskEditValidator"
runat="server"
ControlExtender="Control_DateMaskEditExtender"
ControlToValidate="Control_Date"
Display="Dynamic"
EmptyValueBlurredText="*"
ValidationGroup="MKE" />
<Ajax:CalendarExtender
ID="Control_CalendarExtender"
Format="yyyy/MM/dd"
runat="server"
TargetControlID="Control_Date"
PopupButtonID="ImgBntCalc" />
.aspx ページ
上記のユーザーコントロールを使用する .aspx ページは以下のようになります。下の方のインラインの JavaScript のコードで、コートブロックによって thismonthBegin.TextBoxClientID から id を取得しているところに注目してください。
<%@ Page Language="C#" %>
<%@ Register TagPrefix="Ctrl" TagName="DateCtrl"
Src="~/0014-ClientIDInWebUserControl.ascx" %>
<%@ Register Assembly="AjaxControlToolkit"
Namespace="AjaxControlToolkit" TagPrefix="asp" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<asp:ToolkitScriptManager
ID="ToolkitScriptManager1" runat="server">
</asp:ToolkitScriptManager>
<div>
<Ctrl:DateCtrl ID="thismonthBegin" runat="server" />
</div>
</form>
</body>
</html>
<script type="text/javascript">
//<![CDATA[
window.onload = function () {
var element = document.getElementById(
"<%=thismonthBegin.TextBoxClientID%>");
element.onchange = function () {
alert(element.value);
}
}
//]]>
</script>
注意:
AJAX Control Toolkit の TabContainer や Calendar を使用する際、head 要素内にコードブロック(<% ... %>)を定義すると、"System.Web.HttpException: コントロールにコード ブロック (<% ... %>) が含まれているため、コントロールのコレクションを変更できません。" という例外がスローされるので注意してください。その理由等は先の記事
ACT の TabContainer を見てください。回避策は、上のコード例のように、コードブロックを head タグの外に移動するだけです。