ASP.NET1.1でIValidator.IsValidがfalseとなるコントロールにフォーカスを移動する方法

まずは、単純な例から。

foreach (BaseValidator validator in Page.Validators)
{
    if (!validator.IsValid)
    {
        string clientId =
            Page.FindControl(validator.ControlToValidate).ClientID;
        Page.RegisterStartupScript(
            "set focus",
            String.Format("<script>document.getElementById('{0}').focus();</script>", clientId));
        return;
    }
}

IValidatorというよりBaseValidatorだけど、標準のValidatorは全部BaseValidatorを継承してるから問題なし。
このコードをボタンをクリックしたときに実行するようにしておき、このコードを通ったら目的のページにResponse.Redirectすれば良い*1
Page.FindControl(validator.ControlToValidate).ClientID;でHTMLでのidを取得して、取得したidを使ったJavaScriptをページに仕込む、なんともスマートじゃない方法だけど、これくらいしか思いつかない。


次に、IValidator.IsValidがfalseとなったコントロールの背景色を全て変更しつつ、IValidator.IsValidがfalseとなった一番最初のコントロールにフォーカスを移動するコード。

bool hasInvalid = false;
foreach (BaseValidator validator in Page.Validators)
{
    if (!validator.IsValid)
    {
        string clientId =
            Page.FindControl(validator.ControlToValidate).ClientID;
        if (!hasInvalid)
             Page.RegisterStartupScript("script begin", String.Format("<script>var ", clientId));
        Page.RegisterStartupScript(String.Format("set bg color {0}", clientId),
            String.Format("t=document.getElementById('{0}');t.style.backgroundColor='pink';", clientId));
        if (!hasInvalid)
            Page.RegisterStartupScript("set focus", String.Format("t.focus();"));
        hasInvalid = true;
    }
}
if (hasInvalid)
{
    Page.RegisterStartupScript("script end", "</script>");
    return;
}

初めてIValidator.IsValidがfalseとなった時にスクリプトの開始タグとフォーカス設定用のスクリプトを、IValidator.IsValidがfalseとなったとき全てで背景色を設定するスクリプトを、最後にIValidator.IsValidがfalseとなったものがあった場合に終了タグを生成する。
ここで、背景色を設定するスクリプトを生成する部分で、RegisterStartupScriptの第一引数をString.Formatを使って生成しているけど、これはスクリプトごとに一意になっている必要があるらしいから。


うーん、生成後のスクリプトを見越してこんなロジックになったけど、別にこれでもいいな。どうせグローバル領域に置かれるんだから、varなんて考慮する必要ないし。

bool hasInvalid = false;
foreach (BaseValidator validator in Page.Validators)
{
    if (!validator.IsValid)
    {
        string clientId =
            Page.FindControl(validator.ControlToValidate).ClientID;
        if (!hasInvalid)
            Page.RegisterStartupScript("script begin",
                String.Format("<script>document.getElementById('{0}').focus();", clientId));
        Page.RegisterStartupScript(String.Format("set bg color {0}", clientId),
            String.Format("document.getElementById('{0}').style.backgroundColor='pink';", clientId));
        hasInvalid = true;
    }
}
if (hasInvalid)
{
    Page.RegisterStartupScript("script end", "</script>");
    return;
}

*1:・・・かどうかは良くわからない。動きはするけどね