UpdatePanelにネストされたWebControlのScriptManager.RegisterStartupScriptが機能しない
-
03-07-2019 - |
質問
私は、かなり単純な問題であると信じているものを抱えていますが、私の人生では、問題を見ることができません。この問題はScriptManager.RegisterStartupScriptに関連しています。これは私が以前に何度も使用したことのあるものです。
私が持っているシナリオは、ページに挿入されたカスタムWebコントロールがあるということです。コントロール(および他の1つまたは2つ)は、UpdatePanel内にネストされます。それらは、ページのPlaceHolderに挿入されます。
<asp:UpdatePanel ID="pnlAjax" runat="server">
<ContentTemplate>
<asp:PlaceHolder ID="placeholder" runat="server">
</asp:PlaceHolder>
...
protected override void OnInit(EventArgs e){
placeholder.Controls.Add(Factory.CreateControl());
base.OnInit(e);
}
これはページ上の唯一の更新パネルです。
コントロールを正常に動作させるには、初期JavaScriptを実行する必要があります。コントロールの呼び出し:
ScriptManager.RegisterStartupScript(this, GetType(),
Guid.NewGuid().ToString(), script, true);
そして私も試しました:
ScriptManager.RegisterStartupScript(Page, Page.GetType(),
Guid.NewGuid().ToString(), script, true);
問題は、ページが最初に表示されたときにスクリプトが正しく実行されますが、部分的なポストバック後に再実行されないことです。私は次のことを試しました:
- CreateChildControlsからRegisterStartupScriptを呼び出す
- OnLoad / OnPreRenderからRegisterStartupScriptを呼び出す
- 最初の2つのパラメーターにさまざまなパラメーターの組み合わせを使用する(上記の例では、コントロールはPageで、タイプはGetType()ですが、コントロール自体を使用するなど)
- 永続的なIDと新しいIDを使用しようとしました(これがいずれにせよ大きな影響を与えると信じているわけではありません)。
- いくつかのブレークポイントを使用して、Register行が正しく呼び出されることを確認しました。
私が試したことのない唯一のことは、コントロールが更新パネルを認識する必要があるとは思わないので、UpdatePanel自体をコントロールとタイプとして使用することです更新パネルを取得しますか?)。
上記で私が間違っているかもしれないことを誰でも見ることができますか?
ありがとう:)
さて、上記のクエリに答えるには、プレースホルダーが何らかの形でScriptManager.RegisterStartupScriptを台無しにしているかのように見えます。
プレースホルダーからコントロールを引き出してページに直接コーディングすると、Registerスクリプトが正しく動作します(コントロール自体もパラメーターとして使用しています)。
ScriptManager.RegisterStartupScript(this, GetType(), Guid.NewGuid().ToString(), script, true);
PlaceHolderにコントロールを挿入すると、ScriptManagerがスクリプトを正しく登録できなくなる理由を明らかにすることができますか?これは動的コントロールのライフサイクルと関係があるかもしれないと思いますが、上記の正しいプロセスがあれば(私自身の知る限り)感謝します。
解決
実際には、コントロールのオーバーロードを使用する必要があると思いますRegisterStartupScript。
サーバーコントロールで次のコードを試しました:
[ToolboxData("<{0}:AlertControl runat=server></{0}:AlertControl>")]
public class AlertControl : Control{
protected override void OnInit(EventArgs e){
base.OnInit(e);
string script = "alert(\"Hello!\");";
ScriptManager.RegisterStartupScript(this, GetType(),
"ServerControlScript", script, true);
}
}
次に、私が持っているページで:
protected override void OnInit(EventArgs e){
base.OnInit(e);
Placeholder1.Controls.Add(new AlertControl());
}
Placeholder1は、更新パネルのプレースホルダーです。プレースホルダーには、ボタンなどの他のコントロールがいくつかあります。
これは期待どおりに動作し、<!> quot; Hello <!> quot;という警告が表示されました。ページを読み込むたび、または更新パネルを更新するたびに。
他に確認できることは、更新パネルのリクエスト中に発生するページライフサイクルイベントのいくつかにフックすることです:
Sys.WebForms.PageRequestManager.getInstance()
.add_endRequest(EndRequestHandler);
PageRequestManager endRequestHandler イベントは、更新パネルが完了するたびに発生します更新-これにより、コントロールをセットアップするメソッドを呼び出すことができます。
その他の質問は次のとおりです。
- スクリプトは実際に何をしているのですか?
- おそらく、ページの下部(終了<!> lt; / form <!> gt;タグの直前)のHTMLでスクリプトを見ることができますか?
- いくつかの<!> quot; alert(<!> quot; Here <!> quot;); <!> quot;起動スクリプトを呼び出して、正しく呼び出されているかどうかを確認しますか?
- Firefoxを試しましたが、 Firebug -スクリプトエラーは報告されていますか?
他のヒント
ユーザーコントロールでこれを使用する際に問題が発生しました(ページでは正常に機能しました)。 Button1はupdatepanel
内にあり、scriptmanager
はusercontrol
上にあります。
protected void Button1_Click(object sender, EventArgs e)
{
string scriptstring = "alert('Welcome');";
ScriptManager.RegisterStartupScript(this, this.GetType(), "alertscript", scriptstring, true);
}
最初の2つの引数には注意する必要があるようです。コントロールではなく、ページを参照する必要があります
ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(), "alertscript", scriptstring, true);
ScriptManager.RegisterStartupScriptを呼び出すと、<!> quot; Control <!> quot;パラメーターは、更新されるUpdatePanel内にあるコントロールでなければなりません。次のように変更する必要があります。
ScriptManager.RegisterStartupScript(this, this.GetType(), Guid.NewGuid().ToString(), script, true);
解決策は、スクリプトを外部jsファイル(「yourDynamic.js」と呼ばれる)に配置し、updatepanelを更新するたびにdeファイルを再登録することです。
updatepanel_prerenderイベントでこれを使用します:
ScriptManager.RegisterClientScriptBlock(UpdatePanel1, UpdatePanel1.GetType(), "UpdatePanel1_PreRender", _
"<script type='text/javascript' id='UpdatePanel1_PreRender'>" & _
"include('yourDynamic.js');" & _
"removeDuplicatedScript('UpdatePanel1_PreRender');</script>" _
, False)
ページまたはその他のインクルードには、次のjavascriptが必要です。
// Include a javascript file inside another one.
function include(filename)
{
var head = document.getElementsByTagName('head')[0];
var scripts = document.getElementsByTagName('script');
for(var x=0;x<scripts.length;> {
if (scripts[x].getAttribute('src'))
{
if(scripts[x].getAttribute('src').indexOf(filename) != -1)
{
head.removeChild(scripts[x]);
break;
}
}
}
script = document.createElement('script');
script.src = filename;
script.type = 'text/javascript';
head.appendChild(script)
}
// Removes duplicated scripts.
function removeDuplicatedScript(id)
{
var count = 0;
var head = document.getElementsByTagName('head')[0];
var scripts = document.getElementsByTagName('script');
var firstScript;
for(var x=0;x<scripts.length;> {
if (scripts[x].getAttribute('id'))
{
if(scripts[x].getAttribute('id').indexOf(id) != -1)
{
if (count == 0)
{
firstScript = scripts[x];
count++;
}
else
{
head.removeChild(firstScript);
firstScript = scripts[x];
count = 1;
}
}
}
}
clearAjaxNetJunk();
}
// Evoids the update panel auto generated scripts to grow to inifity. X-(
function clearAjaxNetJunk()
{
var knowJunk = 'Sys.Application.add_init(function() {';
var count = 0;
var head = document.getElementsByTagName('head')[0];
var scripts = document.getElementsByTagName('script');
var firstScript;
for(var x=0;x<scripts.length;> {
if (scripts[x].textContent)
{
if(scripts[x].textContent.indexOf(knowJunk) != -1)
{
if (count == 0)
{
firstScript = scripts[x];
count++;
}
else
{
head.removeChild(firstScript);
firstScript = scripts[x];
count = 1;
}
}
}
}
}
かなりクールで、ああ... jejeje 先ほど投稿した内容のこの部分こちら。
このヘルプをお待ちください...:)
Page.ClientScript.RegisterStartUpScriptで問題が発生しました-更新パネルを使用していませんでしたが、コントロールはキャッシュされていました。これは、スクリプトをリテラルに挿入する必要があったことを意味しました(またはPlaceHolderを使用できました)。そのため、キャッシュからレンダリングするときにスクリプトが含まれます。
同様の解決策が役立つ場合があります。
キーにGUIDを使用しない
ScriptManager.RegisterClientScriptBlock(this.Page, typeof(UpdatePanel)
Guid.NewGuid().ToString(), myScript, true);
そしてそれをしたい場合は、この関数のような何かを呼び出します
public static string GetGuidClear(string x)
{
return x.Replace("-", "").Replace("0", "").Replace("1", "")
.Replace("2", "").Replace("3", "").Replace("4", "")
.Replace("5", "").Replace("6", "").Replace("7", "")
.Replace("8", "").Replace("9", "");
}
私のために働いたのは、次のようにタイプをUpdatePanelのタイプとして指定しながらページに登録することです:
ScriptManager.RegisterClientScriptBlock(this.Page, typeof(UpdatePanel) Guid.NewGuid().ToString(), myScript, true);
スクリプトに構文エラーがある場合は起動しない場合があります。スクリプトとjavascriptの構文が正しいことを確認してください。
ScriptManager.RegisterStartupScript(this, this.GetType(), Guid.NewGuid().ToString(),script, true );
<!> quot; true <!> quot; ScriptManager.RegisterStartupScriptの最後のparam値は、ページ内にJavaScriptタグを追加します。
<script language='javascript' defer='defer'>your script</script >
値が<!> quot; false <!> quotの場合; --script--タグなしでスクリプトのみを挿入します。
多くのことを試してみましたが、最後に最後のパラメーターがfalseでなければならず、Javaスクリプトに<SCRIPT>
タグを追加する必要があることがわかりました:
string script = "< SCRIPT >alert('hello!');< /SCRIPT>";
ScriptManager.RegisterClientScriptBlock(Page, Page.GetType(), key, script, **false**);