WebSurfer's Home

トップ > Blog 1   |   ログイン
APMLフィルター

CalendarExtender の日付の表示

by WebSurfer 2013年7月26日 11:48

Ajax Control Toolkit の CalendarExtender で日本語形式の日付を表示するにはどうすればよいかという話です。

まず、ToolkitScriptManager と CalendarExtender の設定がデフォルト状態(Visual Studio でドラッグ&ドロップしただけの状態)の場合は下の画像のような表示になります。

デフォルトでのカレンダーの表示

カルチャは ja-JP と認識されていますが、(1) TextBox に入力される日付の形式が M/d/yyyy(米国式)、(2) カレンダーの曜日が英語、(3) カレンダーのタイトルと今日の日付の表示が米国式になってしまいます。

特に問題になるのが「(1) TextBox に入力される日付の形式が M/d/yyyy」です。M/d/yyyy 形式では、CompareValidator による検証や、サーバー側での DateTime 型への変換の際などにパースがうまくいかず、期待した結果にならないということがあります。

カルチャが ja-JP の時に TextBox に入力される日付が yyyy/MM/dd 形式となるようにするには、ToolkitScriptManager の EnableScriptGlobalization プロパティを true に設定してやります。その結果が下の画像です。

EnableScriptGlobalization を true に設定

MSDN ライブラリによると、"EnableScriptGlobalization プロパティを true に設定すると、グローバル化された JavaScript 関数がカルチャ固有の情報を表示します" とのことです。

カルチャは、ブラウザ、サーバーコード、または Web サイトの構成ファイルで設定できます。例えば、@ Page ディレクティブで Culture, UICulture を "auto" に設定した場合、ASP.NET がリクエスト情報に含まれる Accept-Language ヘッダの内容から判断して、自動的にカルチャを特定してくれます。

なので、EnableScriptGlobalization プロパティが true に設定してあると、「(1) TextBox に入力される日付の形式」は、カルチャが ja-JP の場合は yyyy/MM/dd 形式、en-US の場合は M/d/yyyy となります。

「(2) カレンダーの曜日」も、カルチャが ja-JP の場合は日本語、en-US の場合は英語で表示されます。下の画像はカルチャが en-US の場合のものです。カルチャが ja-JP の場合のもの(上の画像)と比較してみてください。

カルチャが en-US の場合

なお、TextBox に入力される日付の形式は、CalendarExtender コントロールの Format プロパティで明示的に設定できます。当然、EnableScriptGlobalization プロパティの設定より、こちらの方が優先されます。なので、カルチャに依存させないで固定的に日付の形式を設定したい場合は Format="yyyy/MM/dd" のようにすることができます。

以上の対応で、上記の問題の (1) と (2) は解決できます。しかし、「(3) カレンダーのタイトルと今日の日付の表示」は依然として米国形式のままです。これを解決するには、CalendarExtender コントロールの DaysModeTitleFormat, TodaysDateFormat プロパティで書式を指定してやります。

下の画像は、DaysModeTitleFormat="yyyy年M月" TodaysDateFormat="yyyy年M月d日" とした時のものです。

タイトルと今日の日付を日本語形式に

ただし、Format, DaysModeTitleFormat, TodaysDateFormat プロパティで書式を指定してしまうのは、グローバル化と逆行することになる(他のカルチャに対応できなくなる)ので、そうすることが良いのかどうかはよく考えた方がよさそうです。

参考に、上の画像のカレンダーを表示したコードを載せておきます。

<%@ Page Language="C#" Culture="auto" UICulture="auto" %>
<%@ Import Namespace="System.Threading" %>

<%@ Register Assembly="AjaxControlToolkit" 
  Namespace="AjaxControlToolkit" 
  TagPrefix="asp" %>

<!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 Page_Load(object sender, EventArgs e)
  {
    Label1.Text = "CurrentCulture: " +
        Thread.CurrentThread.CurrentCulture.ToString();
  }
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
  <title></title>
</head>
<body>
  <form id="form1" runat="server">
  <asp:ToolkitScriptManager ID="ToolkitScriptManager1" 
    runat="server" 
    EnableScriptGlobalization="True">
  </asp:ToolkitScriptManager>
  <div>
    <asp:Label ID="Label1" runat="server">
    </asp:Label>
    <br />
    <asp:TextBox ID="TextBox1" runat="server">
    </asp:TextBox>
    <asp:CalendarExtender ID="TextBox1_CalendarExtender" 
      runat="server" 
      Enabled="True" 
      TargetControlID="TextBox1"            
      DaysModeTitleFormat="yyyy年M月" 
      TodaysDateFormat="yyyy年M月d日"
      Format="yyyy/MM/dd" >
    </asp:CalendarExtender>
  </div>
  </form>
</body>
</html>

Tags: ,

AJAX

aspnet_client フォルダとは何?

by WebSurfer 2013年7月24日 17:42

IIS に設定した ASP.NET Web サイトに、aspnet_client というフォルダが自動的に(勝手に)作られていると思いますが、これは何かという話です。

aspnet_client フォルダ

C:\inetpub\wwwroot 直下だけでなく、IIS でサイトに設定したフォルダには aspnet_client フォルダがあるはずです。(サイトではないアプリケーションルートにはないはず)

このフォルダの目的は、簡単に言うと、ASP.NET 1.1 以前で、サーバーコントロールから送られてくるクライアントスクリプトを保持するためのものだそうです。

(2016/6/1 追記:ASP.NET 3.5 まではグローバルテーマを保持するフォルダとしても利用されているそうです。詳しくは、この記事の一番下にリンクを張った Stackoverflow の記事、MSDN の「方法 : ASP.NET ページ テーマを定義する」の中の「グローバル テーマの作成」のセクションを見てください)

サーバーコントロールは、RegisterStartupScript メソッド等を使用してスクリプトを送信することもできますが、これは (1) ページのサイズが増大する可能性がある、(2) スクリプトをブラウザがキャッシュできなくなるという問題があります。

この問題に対処するために、ASP.NET 1.1 以前では aspnet_client という名前のフォルダが使用されています。このあたりの詳細説明は、MSDN ライブラリの ASP.NET 2.0 でのクライアント ファイルの処理 を見てください。

ASP.NET 2.0 以降については、サーバーコントロールのアセンブリにスクリプトファイル等のリソースを埋め込み、HTTP ハンドラ (WebResource.axd) を使って取得するようになっているので(参考: リソース埋め込みカスタムコントロール)、aspnet_client フ���ルダは使われません。

上記の MSDN ライブラリにも ASP.NET 2.0 のリソース埋め込みに関する説明があります。ただし、パラメータの説明などがちょっと古いようですので注意してください。

以上のようなわけで、ASP.NET 2.0 以降であれば aspnet_client フォルダは使わないので、削除しても問題なさそうです。

ただし、Stack Overflow の What is the aspnet_client folder for under the IIS structure? に説明がありますように、Windows Update などで復活することもあるそうです。なので、削除してもあまり意味はないかもしれません。

なお、.NET Framework 4 をインストールすると、aspnet_client フォルダの中に system_web\4_0_3031 というフォルダができるはずですが、これは ASP.NET 4 で aspnet_client フォルダの使用が復活したというわけではなく、もともとそういうフォルダができる仕様になっているそうです。

詳しくは、Stack Overflow の Why did the aspnet_client folder come back in ASP.NET 4? を見てください。

Tags:

ASP.NET

和暦で表示

by WebSurfer 2013年7月12日 17:47

下の画像のように、GridView や ListView 上で日付を「昭和」とか「平成」といった和暦で表示するにはどうしたらよいかという話です。

GridView 上に和暦の日付を表示

単純に Text='<%# Bind("OrderDate", "{0:ggy年M月d日}") %>' としただけではダメです。それだけでは、たとえ CurrentCulture が "ja-JP" でも、表示は「西暦XX年Y月Z日」となってしまいます。

何故かと言えば、カルチャが "ja-JP" のとき、デフォルトで使用されるカレンダーの表示は「西暦XX」になっているからだそうです。ちなみにカルチャが "en-US" のときは「A.D.XX」となります。

これを「昭和」とか「平成」といった和暦で表示するには、デフォルトのカレンダーを、JapaneseCalendar クラス のオブジェクトを生成して、それに差し替えてやります。

以下のコードの Page_Load メソッドの中のコードのような感じです。

<%@ Page Language="C#" Culture="auto" UICulture="auto" %>
<%@ Import Namespace="System.Globalization" %>
<%@ Import Namespace="System.Threading" %>

<!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 Page_Load(object sender, EventArgs e)
  {
    Label2.Text = "CurrentCulture: " + 
        Thread.CurrentThread.CurrentCulture.ToString();

    CultureInfo culture = new CultureInfo("ja-JP");
    culture.DateTimeFormat.Calendar =
        new JapaneseCalendar();
    Thread.CurrentThread.CurrentCulture = culture;
  }

  protected void GridView1_RowUpdating(
      object sender, GridViewUpdateEventArgs e)
  {
    string newOrderDate = (string)e.NewValues["OrderDate"];
  }

  protected void SqlDataSource1_Updating(
      object sender, SqlDataSourceCommandEventArgs e)
  {
    DateTime newOrderDate = 
        (DateTime)e.Command.Parameters["@OrderDate"].Value;
  }
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
  <title></title>
</head>
<body>
  <form id="form1" runat="server">
  <div>
    <asp:Label ID="Label2" runat="server"></asp:Label>

    <asp:SqlDataSource ID="SqlDataSource1" runat="server" 
      ConnectionString="<%$ ConnectionStrings:Northwind %>" 
      SelectCommand="SELECT TOP 10 
        [OrderID], [CustomerID], [OrderDate] FROM [Orders]" 
      UpdateCommand="UPDATE [Orders] 
        SET [CustomerID] = @CustomerID, [OrderDate] = @OrderDate 
        WHERE [OrderID] = @OrderID" 
      OnUpdating="SqlDataSource1_Updating">
      <UpdateParameters>
        <asp:Parameter Name="CustomerID" Type="String" />
        <asp:Parameter Name="OrderDate" Type="DateTime" />
        <asp:Parameter Name="OrderID" Type="Int32" />
      </UpdateParameters>
    </asp:SqlDataSource>

    <asp:GridView ID="GridView1" 
      runat="server" 
      AutoGenerateColumns="False" 
      DataKeyNames="OrderID" 
      DataSourceID="SqlDataSource1" 
      OnRowUpdating="GridView1_RowUpdating">
      <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="OrderDate" 
          SortExpression="OrderDate">
          <EditItemTemplate>
            <asp:TextBox ID="TextBox1" 
              runat="server" 
              Text='<%# Bind("OrderDate", "{0:ggy年M月d日}") %>'>
            </asp:TextBox>
          </EditItemTemplate>
          <ItemTemplate>
            <asp:Label ID="Label1" 
              runat="server" 
              Text='<%# Bind("OrderDate", "{0:ggy年M月d日}") %>'>
            </asp:Label>
          </ItemTemplate>
        </asp:TemplateField>
      </Columns>
    </asp:GridView>
  </div>
  </form>
</body>
</html>

なお、更新する際には、和暦 ⇒ 西暦のパースをしなくても大丈夫です。

MSDN ライブラリの JapaneseCalendar クラス の説明には、"アプリケーションで JapaneseCalendar クラスを使用している場合、DateTime.Parse は年の前に表記される時代 (年号) の省略形を認識します。この省略名は、大文字と小文字を区別しないローマ字 1 文字の省略形または漢字 1 文字の省略形のいずれかです。" とあります。

もちろん省略しないで「平成」「昭和」などとしても認識します。

実際に上のコードで試してみましたが、例えば、TextBox に "H8年8月8日" と入力して[更新]をかけると、GridViewUpdateEventArgs ではそのままの文字列になっているものの、SqlDataSourceCommandEventArgs では正しく DateTime 型にパースされます。結果、DB も正しく更新されます。

ただし、当然ですが、あり得ない日付のパースはできませんので、DropDownList などを利用して入力制限した方がよさそうです。

Tags:

ASP.NET

About this blog

2010年5月にこのブログを立ち上げました。主に ASP.NET Web アプリ関係の記事です。

Calendar

<<  2024年3月  >>
252627282912
3456789
10111213141516
17181920212223
24252627282930
31123456

View posts in large calendar