C# + Visual Studio 2008 開発メモ

ひさしぶりにVisual StudioC#を使っています。次回のために、今回詰まったところをメモ。

ListはSystem.Collections.Generic

まず、つまらないミスの話から。

Listを使いたいのに、インテリセンスに出ない。ArrayListは出る。なぜ?と思ったら、何のことはない、ジェネリクス用の名前空間の指定が抜けていました。

using System.Collections.Generic;

System.Collectionsだけじゃダメなんですね。

ジェネリクスC#2.0から使えるはずなのに、なぜだろう……もしかして今書いてるコードはC#2.0以前なのか? なんて、10分くらい悩みました。考えすぎでした。

GridView内コントロールのVisibleとEnableをデータバインドで制御

実現したいこと

GridViewのタテ一列で、ある行のデータを登録済のときは「登録済」というラベルを表示し、登録前のときは「登録」ボタンを表示する。GridViewにバインドするデータソースには、RegistFlagというbool型の値がある。RegistFlagがTrueなら登録済、Falseなら登録前である。

方法
  • ボタンとラベルの表示を切り替えたい列をTemplateFieldにする。
  • aspxのデザインビューで、GridViewのTemplateFieldを編集する。
  • TemplateFieldにした列を表示し、登録済ラベルのコントロールと登録ボタンのコントロールを並べて配置する。
  • 2つのコントロールのデータバインド項目を編集する。

登録済ラベルの設定

(bool)Eval("RegistFlag")      // RegistFlagがTrueなら表示

登録ボタンの設定

(bool)Eval("RegistFlag")==false   // RegistFlagがfalseなら表示

これでOK。どっとねっとふぁんBlogさんの記事が参考になりました。
dotnetfan.org - このウェブサイトは販売用です! -&nbspdotnetfan リソースおよび情報

昨年Visual StudioC#を使ったときは、この方法を知らなかったので、コードビハインドで書いていました。

if(RegistFlag)
{
    SubmitRegist.Visible = true      // 登録ボタン
    AfterRegist.Visible = false      // 登録済ラベル
}
else
{
    SubmitRegist.Visible = false
    AfterRegist.Visible = true
}

みたいな。上では単純化して書いたけど、本当はたしか、RowsとCellsとFindControlを使って行数文だけforで回し、Visibleの値を設定する必要があったと思う。その上、RegisFlagの値を取得するために、次の手順が必要でした。

  • RegistFlagをバインドした列を新規に作る。
  • その列をTemplateFieldにする。
  • 列のVisibleをFalseにする。

RegistFlagは、表示制御で使うためにバインドしたい。しかし、GridViewには表示したくない。だから、こうする必要がありました。単純にバインドしてFalseにすると値が渡らないらしいので、わざわざTemplateFieldにしてからFalseにしていたという。

こんな辛い記述から解放されました。

GridView内のボタンを使って引数を渡す

  • GridViewのプロパティを編集して、RowCommandイベントで実行するメソッドを指定する。GridView名_RowCommadってかんじでOK。
  • ButtonFieldをTemplateFieldにする。
  • aspxのデザインビューで、GridViewのTemplateFieldを編集する。
  • TemplateFieldにした列を表示し、ボタンのデータバインド項目を編集する。

ボタンのデータバインド項目に、e.CommandArgumentというパラメータがあるので、ボタンをクリックしたときに渡したい値をバインドします。たとえば、UserIDとか。

これによって、GridView名_RowCommadメソッド内で、バインドに設定したUserIDを取得できます。具体的には、引数のイベントオブジェクト(たとえばe)を使って、e.CommandArgumentでUserIDの値を取得します。

この方法を使えば、UserIDをHiddenFieldで渡さなくてもOKです。

GridView内のボタンをクリックしたとき選択行を特定する方法

たぶんいくらでもやり方はあるのだろうけど、初心者(私)でも思いつくのは、次の2つの方法です。

キーとなるIDを渡す or 行番号を渡す

さて、どっち? 使い分けはこうです。

選択行を特定した後、キーとなるIDのみ使いたいとき
上で書いたように、ボタンクリックイベントの引数として、キーとなるIDを渡せばよいと思います。たとえば、UserIDのみ受け取って、ボタンクリック後にもう一度データベースを検索する場合。
選択行を特定した後、キーとなるIDおよび行番号を使いたいとき
ボタンクリックイベントの引数として、行番号を渡します。ボタンクリックイベントの引数としてIDを渡してしまうと、行番号を渡すことができなくなります。

注意するのは、行番号を渡したい場合、ボタンを配置する列をTemplateFieldに変換せず、ButtonFieldのまま使うこと。なぜなら、ButtonFieldだと、デフォルトで引数に行番号が入るためです。TemplateFieldにしてしまうと、行番号を取得できない。

e.CommandArgumentに値をバインドして引数にできるとわかって、喜んで実装したものの、実は引数だけでなく行番号も必要だった……というのが、私がやってしまったパターンです。TemplateFieldを廃してButtonFieldを作り直し、e.CommandArgumentで取れる値をIDでなく行番号と想定してメソッドを書き直す、といった手間がかかりました。

特に、最後のこの件は、しばらくたったら忘れてまたやりそうなので、メモに残しておきます。