今回はC#とASP.NETの話です。
Webページで登録画面を作成していて、
必須入力項目への入力確認に、
RequiredFieldValidatorクラスを使用しました。
バリデーションを行うコントロール名とエラーメッセージをセットすれば、
指定したコントロールに対して、入力がなされたかクライアント側で確認することができます。
ただし、今回作成している画面が少し厄介で、
ドロップダウンリストの選択した値によって、
必須入力が変更される、という仕様を盛り込んでいました。
そこで、SelectedIndexChangedイベントを使用し、
選択した値が変更した時に、RequiredFieldValidatorの設定を切り替えるようにしました。
初めは、選択した値ごとに、RequiredFieldValidatorのEnabledプロパティに
TrueやFalseをセットしていたのですが、
これだと、Falseのセット漏れが出たりするなぁ、と思い、
一度、ページ内の全てのRequiredFieldValidatorにFalseをセットした後、
必要なコントロールのみ、Trueを設定しようと考えました。
では、どの様にして、全てのRequiredFieldValidatorコントロールに
Falseをセットするのか、考えました。
ASP.NETの各コントロールが継承するクラスにControlクラスが有ります。
このControlクラスには、FindControlというメソッドが有りますが、
これはコントロールのIDでしか探せません。
それに加え、コントロールは階層配置されており、
FindControlメソッドでは、呼出元のコントロールが有する子コントロールが
対象となります。
そこで、下記の記事を参考にし、再帰的に呼び出されるメソッドを作成しました。
下記記事では、IDを使用していますが、今回はクラス名で検索する様にします。
方法: ID を使用してサーバー コントロールにアクセスする
http://msdn.microsoft.com/ja-jp/library/y81z8326(v=vs.100).aspx
上記記事内に記載されているメソッドからの変更点は、
1.引数のIDをクラス名に変更する。
2.コントロールとIDの照合を
コントロールのクラス名と1で変更した引数と照合する。
public static Control FindControlRecursive(Control rootControl,
string findControlClassName)
{
if (rootControl.GetType().Name == findControlClassName)
{
return rootControl;
}
foreach (System.Web.UI.Control searchControl in rootControl.Controls)
{
Control controlToReturn =
FindControlRecursive(searchControl, findControlClassName);
if (controlToReturn != null)
{
return controlToReturn;
}
}
return null;
}
このメソッドを実行することで、rootControl以下のコントロールから
検索対象とするクラス名を有するコントロールを取得できます。
後は、取得したコントロールのparentプロパティで、
直近の親コントロールを取得し、
親コントロールが持つ子コントロールをforeachで回し、
GetType().Name で同一のクラス名を持つコントロールのEnabledプロパティに
FALSEをセットすれば、Webページ内のRequiredFieldValidatorオブジェクトを
無効化できます。
ちなみに、呼出元は以下の様なコードを書きました。
// ページ内のコントロールを対象とする。
foreach (Control pageChild in Page.Controls)
{
// RequiredFieldValidatorクラスのコントロールを検索する。
var findControl = FindControlRecursive(pageChild,
"RequiredFieldValidator");
if (findControl != null)
{
// 検索結果のコントロールの親コントロールを取得する。
var parentControl = findControl.Parent;
// 親コントロールの全てのvalidatorを無効にする。
foreach (Control childControl in parentControl.Controls)
{
If (childControl.GetType().Name == "RequiredFieldValidator")
{
RequiredFieldValidator requiredFieldControl =
(RequiredFieldValidator)childControl;
requiredFieldControl.Enabled = false;
}
}
}
}
サーバサイドで同一のクラスを持つコントロールに
一律の操作をする際に、使えると思います。