WebSurfer's Home

トップ > Blog 1   |   Login
Filter by APML

GridView と jQuery UI DatePicker

by WebSurfer 26. October 2014 15:47

ASP.NET の GridView で jQuery UI の Datepicker を使用する例の紹介です。

GridView に jQuery UI の Datepicker

GridView と組み合わせるなら Ajax Control Toolkit の CalendarExtender を使う方が簡単で、かつ 日付表示の日本語対応 もやりやすいと思いますが、外観の統一を図るなどの理由で jQuery UI の Datapicker を使用したい場合があると思います。

その場合、どのように GridView 内で Datapicker を表示する TextBox を探して、その jQuery オブジェクトを取得し、それに datepicker() メソッドを適用するかを書きます。

通常、GridView では編集モードになった行に TextBox を表示してユーザー入力を受け付けるようにします。その時に datepicker() メソッドを当該 TextBox に適用すればいいわけです。

編集モードになった行は GridView.EditIndex プロパティで判定できますが、Page.Load のタイミングでは早すぎて判定できません。

GridView.RowEditing のタイミングでは、ユーザー入力用の TextBox が生成されていないので FindControl では取得できず、このタイミングでもダメです。

GridView.RowCreated のタイミングでは、最終的な TextBox.ClientID が取得できないので、これまたダメです。(このタイミングでは TextBox.ClientID にはまだ名前つきコンテナの id が付与されておらず TextBox1_x のようになります。最終的な TextBox.ClientID が取得できないと、クライアントスクリプトでその jQuery オブジェクトを取得できません)

GridView.PreLender のタイミングなら、編集モードになっているか否かおよび編集モードになっている行のインデックスは正しく判定できます。最終的な TextBox.ClientID も取得できます。

GridView の[編集]ボタンクリックでポストバックされた際に、GridView.PreLender イベントのハンドラで編集モードになっている行の中の Datapicker を適用する TextBox を探し、その ClientID を取得し、RegisterClientScriptBlock メソッド を使って当該 TextBox に datepicker() メソッドを適用するスクリプトを登録してやることで Datapicker を表示することができます。

以下のコードの GridView1_PreRender イベントハンドラののコードような感じです。GridView で[編集]ボタンをクリックして表示される TextBox にフォーカスを当てると、上の画像のように Datapicker が表示されます。

<%@ Page Language="C#" %>

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

<script runat="server">    
  protected void GridView1_PreRender(object sender, EventArgs e)
  {
    int index = GridView1.EditIndex;

    if (index >= 0)
    {
      TextBox tb = 
        (TextBox)GridView1.Rows[index].FindControl("TextBox1");

      if (tb != null)
      {
        ClientScriptManager cs = Page.ClientScript;
        Type cstype = this.GetType();
        string csname = "jQueryUiDatepicker";

        if (!cs.IsClientScriptBlockRegistered(cstype, csname))
        {
          string cstext = "$(function () { $('#" 
              + tb.ClientID + "').datepicker(); });";

          cs.RegisterClientScriptBlock(
              cstype, 
              csname, 
              cstext, 
              true);
        }
      }
    }
  }
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
  <title>jQuery UI Datepicker in GridView</title>
  <script src="Scripts/jquery.js" type="text/javascript">
  </script>
  <script src="Scripts/jquery-ui.js" type="text/javascript">
  </script>
  <link href="css/jquery-ui.css" rel="stylesheet" type="text/css" />
</head>
<body>
  <form id="form1" runat="server">
  <asp:SqlDataSource ID="SqlDataSource1" runat="server" 
    ConnectionString="<%$ ConnectionStrings:Northwind %>" 
    SelectCommand="SELECT TOP 10 
      [OrderID], [CustomerID], [ShippedDate] 
      FROM [Orders]" 
    UpdateCommand="UPDATE [Orders] 
      SET [CustomerID] = @CustomerID, 
          [ShippedDate] = @ShippedDate 
      WHERE [OrderID] = @OrderID">
    <UpdateParameters>
      <asp:Parameter Name="CustomerID" Type="String" />
      <asp:Parameter Name="ShippedDate" Type="DateTime" />
      <asp:Parameter Name="OrderID" Type="Int32" />
    </UpdateParameters>
  </asp:SqlDataSource>

  <asp:GridView ID="GridView1" 
    runat="server" 
    AutoGenerateColumns="False" 
    DataKeyNames="OrderID" 
    DataSourceID="SqlDataSource1" 
    OnPreRender="GridView1_PreRender">
    <Columns>
      <asp:CommandField ShowEditButton="True" />
      <asp:BoundField DataField="OrderID" 
        HeaderText="OrderID" 
        InsertVisible="False" 
        ReadOnly="True" 
        SortExpression="OrderID" />
      <asp:BoundField DataField="CustomerID" 
        HeaderText="CustomerID" 
        SortExpression="CustomerID" />
      <asp:TemplateField HeaderText="ShippedDate" 
        SortExpression="ShippedDate">
        <EditItemTemplate>
          <asp:TextBox ID="TextBox1" 
            runat="server" 
            Text='<%# Bind("ShippedDate") %>'>
          </asp:TextBox>
        </EditItemTemplate>
        <ItemTemplate>
          <asp:Label ID="Label1" 
            runat="server" 
            Text='<%# Bind("ShippedDate") %>'>
          </asp:Label>
        </ItemTemplate>
      </asp:TemplateField>
    </Columns>
  </asp:GridView>
  </form>
</body>
</html>

サーバー側のコードで TextBox.ClientID を取得してピンポイントなスクリプトを設定しなくても、クライアント側で jQuery のセレクタで当該 TextBox を探して、それに datepicker() 適用する方が簡単ですが、ClientID の命名規則が変わるとうまくいかなくなる可能性があります。

そのリスクが許容できるのであれば、GridView1_PreRender イベントハンドラに代えて、以下のようなクライアントスクリプトを使っても同等なことが可能です。

<script type="text/javascript">
//<![CDATA[
  $(function () { 
    $('#<%=GridView1.ClientID%> input:text[id*=TextBox1]')
      .datepicker(); 
  });
//]]>
</script>

Tags: , ,

JavaScript

About this blog

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

Calendar

<<  December 2019  >>
MoTuWeThFrSaSu
2526272829301
2345678
9101112131415
16171819202122
23242526272829
303112345

View posts in large calendar