背景:既存のASP .NET/C#アプリケーションをカスタマイズしています。独自の小さな「フレームワーク」と、機能を拡張/カスタマイズするときに開発者が従うべき規則があります。現在、その管理機能の一部を拡張しており、フレームワークはSystem.Web.UI.Control
を返すGetAdministrationInterface()
メソッドの実装を強制するコントラクトを提供します。このメソッドはPage_Load()
GUIインターフェースをホストするページのメソッド。
問題: GUIに3つのボタンがあり、それぞれにイベントハンドラーが割り当てられています。私の管理GUIはまったく問題なく読み込まれますが、ボタンをクリックしても期待したとおりには動作しません。ただし、もう一度クリックすると、ボタンは機能します。
各イベントハンドラーメソッドの先頭にブレークポイントを配置し、コードをステップ実行しました。最初のクリックでは、イベントハンドラはトリガーされませんでした。 2回目のクリックで、彼らは解雇しました。
何か案は?
ボタン定義の例(GetAdministrationInterface
内)
public override Control GetAdministrationInterface()
{
// more code...
Button btn = new Button();
btn.Text = "Click Me!";
btn.Click += new EventHandler(Btn_Click);
// more code...
}
イベントハンドラメソッド定義の例
void Btn_Click(object sender, EventArgs e)
{
// Do Something
}
Page_Load
GetAdministrationInterface
を呼び出すメソッド
protected void Page_Load(object sender, System.EventArgs e)
{
if (!Page.IsAsync)
{
List<AdministrationInterface> interfaces = <DATABASE CALL>;
foreach(AdministrationInteface ai in interfaces)
{
placeholderDiv.Controls.Add(ai.GetAdministrationInterface());
}
}
}
悲しみ!こんなバカなものになるだろうと思った。もちろん、純粋に私のせいであり、ASP .NET。
多数のGoogle検索を実行し、自動化されたスクリプトを実行しているボットである疑いで最終的にGoogleによってブロックされた後、私はなんとか最後の1回の検索で絞り込んで、この article を見つけました。すでにあきらめる時点で、一度に10行をスキップしたり、きれいな写真を探したりせずに、記事を読むために最善を尽くしました。 動的に作成されたコントロールへのIDの割り当てというタイトルのセクションで、私はこれらの魔法で最も楽しい言葉を読みました。
動作しないボタンをクリックする前とクリックした後にソースHTMLを表示すると、小さな違いに気付くでしょう。ボタンには、ポストバックの前後で異なるHTML IDがあります。ポストバックの前にctl04とctl05を取得し、ポストバックの後にctl02とctl03を取得しました。
ASP.NETボタンは、Request.FormコレクションのIDの値を確認することにより、イベントを認識します。 (実際には、異なる方法で発生し、コントロールはRequest.Formコレクション自体をチェックしません。ページは、投稿データをIDによってコントロールに送信し、投稿データについて通知するように登録されているコントロールに送信します)。ボタンのIDがポストバック間で変更されているため、ASP.NETはClickイベントを発生させません。クリックしたボタンと後に表示されるボタンは、ASP.NETの異なるボタンです。
案の定、最初にHTMLを表示したとき、ボタンにはctl04$ctl36
。ボタンをクリックすると、ボタンのIDがctl04$ctl33
。
だからあなたはそれを持っています!私がしなければならなかったのは、ボタンにIDを設定するだけでした。イベントハンドラーが呼び出されるようになりました!
サンプルソリューション:
public override Control GetAdministrationInterface()
{
// more code...
Button btn = new Button();
btn.Text = "Click Me!";
// !!THE BANE OF MY EXISTENCE!!
btn.ID = "The_Bane_of_My_Existence";
// !!THE BANE OF MY EXISTENCE!!
btn.Click += new EventHandler(Btn_Click);
// more code...
}
2日間を過ごすのに最高の方法...
私は同じ問題を抱えていましたが、ここで受け入れられた答えはそれを引き起こしていませんでした。テキストボックスと検索ボタンがあり、最初にボタンをクリックしても検索は実行されませんでした。ボタンのイベントハンドラがヒットしていませんでした。しかし、ボタンをもう一度クリックすると、サーバーでイベントがトリガーされました。その理由は次のとおりです。
<asp:Textbox>
のAutoPostBack
がtrue
に設定されている場合、テキストボックスに入力してからボタンをクリックして移動すると、テキストボックスはすぐにポストバックします。フォーカスを失った瞬間。そのため、ボタンのクリックもカウントされません(ページはテキストボックスのイベントの結果として既にポストバックされています)。そのため、ボタンをもう一度クリックすると、テキストボックスが2番目のポストバックに関与しないため、ボタンが機能します。
この問題を解決するには、<asp:Textbox>
のAutoPostBack
プロパティをfalse
に設定します。
簡単な修正方法は、ページに読み込んでいるASCXコントロールにIDを設定することです。たとえば、コードが次のような場合:
UserControl SpecsControl = (UserControl)Page.LoadControl("../name.ascx");
SpecsContainer.Controls.Add(SpecsControl);
次に、行を追加する必要があります(Controls.Addの前)。
SpecsControl.ID = "Aribtrary_Name";
その後、最初のクリックでハンドラーメソッドが起動されます。
私にとってはUpdatePanel
で、ButtonとTextBoxは両方ともUpdatePanel
の中にあったので、ポストバックすると、奇妙な動作を引き起こしました。それはUpdatePanel
の外側にあり、それを修正しました。
私は同じ問題に直面していました。最初のクリック後にボタンがフリーズしました。私にとって、この厄介な問題は、ボタンのEnableViewState
属性を無効にすると解決しました。
私も同じ問題を抱えていました。原因は「localhost:1656/secure/login.aspx?ReturnUrl =%2f」でした。リクエストにクエリ文字列として%2fが含まれている場合、「%2f」が「/」を表していても、最初の投稿は成功しません。
ページロードで条件チェックを行うことでこれを回避する1つの方法
protected void Page_Load(object sender, EventArgs e)
{
string queryString = Request.QueryString.ToString();
if(queryString == "ReturnUrl=%2f")
{
Response.Redirect("/secure/login.aspx");
}
}
完全なPage_loadメソッドを見ずに正確に知ることは困難ですが、ページがリロードされるまでイベントハンドラーが接続されないように少し臭いがします。
例えば:
if (IsPostBack) {
// Add handlers here ...
}
同じ問題がありました。インターネットで検索したところ、解決策が見つかりませんでした。その後、サンプルコードを見つけて使用しました。それは私のために働いた。 Webサイトのリンクは次のとおりです。