- PR -

動的に生成したボタンのイベントが拾えない

投稿者投稿内容
まさ
会議室デビュー日: 2008/06/06
投稿数: 5
投稿日時: 2008-06-06 11:50
環境は、Visual Web Developer 2008 Express Editon with C# です。
データベースは、Oracle 10g Express Edition です。

触り始めて、1週間程度ですので、お手やらかに。
次のようなコードで、Oracleから取得した値をテーブルに表示しています。ここでreaderは、System.Data.OracleClient.OracleDataReaderラスのオブジェクト、Menuは、System.Web.UI.WebControls.Tableクラスのオブジェクトです。

while (reader.Read())
{
  object[] values = new object[3];
  int i = reader.GetOracleValues(values);
  TableRow r = new TableRow();
  TableCell delcom = new TableCell();
  Button delButton = new Button();
  delButton.Click += new EventHandler(delButton_Click);
  delButton.Text = "削除";
  delcom.Controls.Add(delButton);
  r.Cells.Add(delcom);
  for (int j = 0; j < 3; j++)
  {
    TableCell cell = new TableCell();
    cell.Text = values[j].ToString();
    r.Cells.Add(cell);
  }
  Menu.Rows.Add(r);
}

このコードは、メソッドにして、Page_Loadおよび、delButton_Clickの両メソッドから呼び出しています。
ここで、各行に貼り付けた「削除」ボタンを押すと、1回目では削除されず、2回目で削除されるという現象が起きています。
デバッガで追うと、1回目はdelButton_Clickメソッドが呼ばれず、2回目では呼ばれています。
1回目の表示では、設定したイベントが
色々、調べてみましたが、ちょっとお手上げです。

どのようにすれば、毎回この設定したイベントが有効になるかお知恵を拝借できないでしょうか?
よろしくお願いします。
べる
ぬし
会議室デビュー日: 2003/09/20
投稿数: 1093
投稿日時: 2008-06-06 14:56
そのメソッドはPage_Loadのどこでよんでますか?
(!IsPostBack の中か、IsPostBackの中か、判定してないか)

最初にnew Button();したボタンと、2回目のボタンのインスタンスは別ですよね。
まさ
会議室デビュー日: 2008/06/06
投稿数: 5
投稿日時: 2008-06-06 15:11
Page_Loadは、基本的にこのメソッドを呼ぶだけの処理です。
判定は行わずに、常に呼んでます。
べる
ぬし
会議室デビュー日: 2003/09/20
投稿数: 1093
投稿日時: 2008-06-06 16:50
コード:
protected void Page_Load(object sender, EventArgs e)
{
    テーブル作成メソッド();
}

protected void delButton_Click(object sender, EventArgs e)
{
    //削除処理?
    
    テーブル作成メソッド();
    
    //削除処理?
}

こんな感じですか?削除処理はどこでやってますか?
テーブル作成の後だと、削除されたことがテーブルに反映されませんよね。

あと、どの(どの行の)削除ボタンが押されたかをどうやって判断していますか?
まさ
会議室デビュー日: 2008/06/06
投稿数: 5
投稿日時: 2008-06-06 17:04
お世話になります。

protected void Page_Load(object sender, EventArgs e) {
try {
Refresh_Table():
} catch (Exception exp) {
ラベルへのexpのメッセージを設定
}
}

protected void Refresh_Table() {
データベースへの接続など;
TableクラスのオブジェクトのMenuに対してMenu.Rows.Clear();
1行目に見出し行を動的に生成して挿入

 ここが、問題のコード
}

protected void delButton_Click(object sender, EventArgs e)
{
削除処理;
Refresh_Table();
}

といった感じです。

_________________
べる
ぬし
会議室デビュー日: 2003/09/20
投稿数: 1093
投稿日時: 2008-06-06 19:16
クリックイベントが共通ならどの行のボタンが押されたか判断できませんよね。
再度お尋ねしますが、どうやってそれを判断していますか?
(クリックされた行のレコードのみ削除する、という認識であってますよね)

まず、初回アクセス時のdelButton.Click += は意味がないというのはOKでしょうか。
(ボタン押下イベントが発生することはないので)

そしてボタン押下時ですが、まずPage_Loadから呼ばれたRefresh_Tableでイベントハンドラが
設定されます。でもここでnew Button();したボタンが、押されたボタンと同じものかを
判断できないので、イベントが起こるかは不確定になります。

delButtonのIDを、レコードごとに一意なもので固定してやれば多分大丈夫です。

というか、こういった処理はGridViewとか使うとかなり楽ですよ。
まさ
会議室デビュー日: 2008/06/06
投稿数: 5
投稿日時: 2008-06-07 11:55
やはり、タイミングの問題ですね。

行の判定は、sender.Parent.Parentを取って、同じ行のnameを取得しています。
nameが主キーですので、これで削除ができます。

実は、ちょっとした教材を作ってまして、Oracleを直接使用する例を示したかったんです。
GridViewは、楽ですけれど、あえて・・・

ありがとうございました。
べる
ぬし
会議室デビュー日: 2003/09/20
投稿数: 1093
投稿日時: 2008-06-08 09:39
引用:
行の判定は、sender.Parent.Parentを取って、同じ行のnameを取得しています。
nameが主キーですので、これで削除ができます。

実は、ちょっとした教材を作ってまして、Oracleを直接使用する例を示したかったんです。
GridViewは、楽ですけれど、あえて・・・

なるほどそういうことでしたか。

タイミングの問題というか、押下されたボタンの特定の問題です。
主キーを取得しているのなら

Button delButton = new Button();
の直後に
delButton.ID = 主キー; //あるいは(主キー+固定の何か)
とすれば、毎回イベントが呼ばれると思います。

スキルアップ/キャリアアップ(JOB@IT)