WebSurfer's Home

トップ > Blog 1   |   Login
Filter by APML

CheckBox 付き Calendar(その2)

by WebSurfer 12. December 2013 21:24

先の記事 CheckBox 付き Calendar コントロール で「チェックを入れる/外すたびにいちいちポストバックしないでもすむ方法を考え付いたら、別途記事を書きます」と書きましたが、今頃になってそれを作ってみました。

CheckBox 付き Calendar

前のサンプルでは、CheckBox の onclick 属性にポストバックするスクリプトを設定して、CheckBox がクリックされるたびポストバックしてサーバ側でチェック結果を取得して ViewState に保存していました。

それをやめて、別の月に移動する時またはボタンクリックしてポストバックされる時にまとめてクライアント側でチェック結果を取得し、それをサーバーに送信して ViewState に保存するようにしました。

以下にそのコードを示します。詳しくはコメントに書きましたので、それを見てください。

また、実際に動かして試すことができるよう 実験室 にアップしました。興味のある方は試してみてください。

<%@ Page Language="C#" %>
<%@ Import Namespace="System.Collections.Generic" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
  // CheckBox をクリックするたびポストバックしないで、ページン
  // グでポストバックした際に、まとめてチェック結果を取得し、
  // リスト checkedDates を更新する。

  // チェックされている日付のリスト。ViewState に保持する。
  protected List<DateTime> checkedDates;

  protected void Page_Load(object sender, EventArgs e)
  {
    // ViewState から日付リスト checkedDates を取得。
    object obj = ViewState["CheckedDates"];
    if (obj != null)
    {
      checkedDates = (List<DateTime>)obj;
    }
    else
    {
      // ViewState が未設定の場合は新たに初期化。
      checkedDates = new List<DateTime>();
    }
        
    // ポストバックの時は、隠しフィールドでポストされたデータ
    // で日付リスト checkedDates を更新する。
    if (Page.IsPostBack)
    {
      char[] chars = new char[] { ',' };
      string s = 
          Request.Form["__CHECKEDIDLIST"].Trim(chars);
      string[] check = s.Split(chars);
      s = Request.Form["__UNCHECKEDIDLIST"].Trim(chars);
      string[] uncheck = s.Split(chars);

      foreach (string id in check)
      {
        if (!String.IsNullOrEmpty(id))
        {
          checkedDates.Remove(DateTime.Parse(id));
        }
      }

      foreach (string id in uncheck)
      {
        if (!String.IsNullOrEmpty(id))
        {
          checkedDates.Remove(DateTime.Parse(id));
        }
      }

      foreach (string id in check)
      {
        if (!String.IsNullOrEmpty(id))
        {
          checkedDates.Add(DateTime.Parse(id));
        }
      }

      ViewState["CheckedDates"] = checkedDates;
    }

    // form を送信する際、CheckBox のチェック有無を調べて、
    // その結果をサーバーに送信するスクリプトを設定。
    String csname = "OnSubmitScript";
    Type cstype = this.GetType();
    ClientScriptManager cs = Page.ClientScript;
    if (!cs.IsOnSubmitStatementRegistered(cstype, csname))
    {
      String cstext =
        "getCheckedDates('" + Calendar1.ClientID + "');";
      cs.RegisterOnSubmitStatement(cstype, csname, cstext);
    }
  }    

  protected void Calendar1_DayRender(object sender, 
      DayRenderEventArgs e)
  {
    CheckBox cb = new CheckBox();

    // このセルの日付を CheckBox の ID に設定。
    cb.ID = e.Day.Date.ToShortDateString();

    // このセルの日付がリスト checkedDates にあれば CheckBox
    // にチェックを入れる。
    foreach (DateTime day in checkedDates)
    {
      if (e.Day.Date == day)
      {
        cb.Checked = true;
        e.Cell.Controls.Add(cb);
        return;
      }            
    }
        
    cb.Checked = false;
    e.Cell.Controls.Add(cb);
  }

  // ボタンクリックで最終結果を取得。
  protected void Button1_Click(object sender, EventArgs e)
  {
    string str = "Selected Dates:";
    foreach (DateTime day in checkedDates)
    {
      str += "<br />" + day.ToShortDateString();
    }
    Label1.Text = str;
  }
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
  <title>Calendar with CheckBox</title>
  <script src="Scripts/jquery-1.6.2.min.js" type="text/javascript">
  </script>
  <script type="text/javascript">
  //<![CDATA[
    // CheckBox のチェック有無を調べて、その結果を隠し
    // フィールドに設定するスクリプト。
    function getCheckedDates(calendarClientId) {
      var checked = "";
      var unchecked = "";

      $('#' + calendarClientId + ' input:checkbox').each(
        function () {
          // MasterPage を使うなど、名前付コンテナに Calendar
          // を入れると id が違ってくるので注意。
          var id = $(this).attr('id');                    
          if ($(this).attr('checked') == "checked") {
            checked += ',' + id;
          } else {
            unchecked += ',' + id;
          }
        });

      $('#__CHECKEDIDLIST').val(checked);
      $('#__UNCHECKEDIDLIST').val(unchecked);
    }
  //]]>
  </script>
</head>
<body>
  <form id="form1" runat="server">

  <%--チェック結果をサーバに送信する隠しフィールド。--%>
  <input type="hidden" 
    name="__CHECKEDIDLIST" 
    id="__CHECKEDIDLIST" 
    value="" />
  <input type="hidden" 
    name="__UNCHECKEDIDLIST" 
    id="__UNCHECKEDIDLIST" 
    value="" />

  <div>
    <asp:Calendar ID="Calendar1" 
      runat="server" 
      ondayrender="Calendar1_DayRender" 
      SelectionMode="None" >
    </asp:Calendar>
    <asp:Button ID="Button1" 
      runat="server" 
      Text="Show selected dates" 
      onclick="Button1_Click" />
    <br />
    <asp:Label ID="Label1" runat="server" />        
  </div>
  </form>
</body>
</html>

Tags:

ASP.NET

About this blog

2010年5月にこのブログを立ち上げました。その後 ブログ2 を追加し、ここは ASP.NET 関係のトピックス、ブログ2はそれ以外のトピックスに分けました。

Calendar

<<  June 2021  >>
MoTuWeThFrSaSu
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

View posts in large calendar