[FlexGrid for WinForms] Windows 10 April 2018 Updateが適用された環境において、2019/5/1以降の日付に対してColumn.Formatで指定した書式が適用されない

文書番号 : 83053     文書種別 : 既知の問題     登録日 : 2018/07/17     最終更新日 : 2019/07/29
文書を印刷する
対象製品
ComponentOne for WinForms
ステータス
修正済み
詳細
Windows 10 April 2018 Updateが適用された環境において、Column.Formatで指定した書式が、「2019/5/1」以降の日付に対しては適用されない場合があります。​
 例)Formatを「yyyy/MM/dd」と設定した日付型の列で、「2019/05/01」を入力すると、「2019/05/01 0:00:00」と表示されます。

【追加情報】
日付型の列のフィルタリングについて:
同環境において、同様に日付型の列にFormatを指定し、「2019/5/1」以降の日付を含む列でフィルタリングを行おうとすると、エラーが発生することも確認されています。
回避方法
この問題は2019J v1(4.0.20191.362)で修正されました。

FlexGridでは、以前は、元号に関するレジストリキー値に基づいた年号表記データを内部的に配列として保持して処理を行っていましたが、この修正により、(内部配列として持たずに)レジストリキー値から直接処理するように変更されました。

※修正版を適用しない場合の回避方法は以下の通りです。

C1FlexGridの以前のバージョンでは、元号表記を行うために、標準のJapaneseCalendarクラスを使用し、元号に関するレジストリキー値に基づいた年号表記データを内部的に配列として保持して処理を行いました。

Windows 10 April 2018 Updateでは、新元号に関するダミーのレジストリキー値("2019 05 01"="??_?_??????_?")が追加されましたが、C1FlexGridではこれに対応する配列値が存在しないため、「2019/05/01」以降の日付に対してFormatを適用できず、例外処理として既定の日付フォーマット(「yyyy/MM/dd 0:00:00」)に置き換えます。

日付型の列のフィルタリングに関する現象も、同様に上述したダミーのレジストリキー値を内部的に処理できないことが原因で発生します。

【回避方法①】

以下のレジストリキーからダミーの元号設定("2019 05 01"="??_?_??????_?")を削除します。
HKEY_LOCAL_MACHINE¥SYSTEM¥CurrentControlSet¥Control¥Nls¥Calendars¥Japanese¥Eras

【回避方法②】

Formatを指定する代わりに、オーナー描画機能を利用して、テキストをParse(e.Text).ToString("yyyy/MM/dd")という形で変換します。

◎サンプルコード(VB)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
  C1FlexGrid1.Cols(1).Name = "DateTime"
  C1FlexGrid1.Cols(1).WidthDisplay += 100
  C1FlexGrid1.Cols(1).DataType = GetType(DateTime)
  'C1FlexGrid1.Cols(1).Format = "yyyy/MM/dd"
  C1FlexGrid1(1, 1) = New DateTime(2019, 5, 1, 0, 0, 0)
  C1FlexGrid1.DrawMode = C1.Win.C1FlexGrid.DrawModeEnum.OwnerDraw
  C1FlexGrid1.AllowFiltering = True
End Sub

Private Sub C1FlexGrid1_OwnerDrawCell(sender As Object, e As OwnerDrawCellEventArgs) Handles C1FlexGrid1.OwnerDrawCell
  If (e.Col = 1) And (e.Row > 0) Then
    If e.Text = "" Then
      Return
    Else
      e.Text = DateTime.Parse(e.Text).ToString("yyyy/MM/dd")
    End If
  End If
End Sub

◎サンプルコード(C#)
private void Form1_Load(object sender, EventArgs e)
{
  c1FlexGrid1.Cols[1].Name = "DateTime";
  c1FlexGrid1.Cols[1].WidthDisplay += 100;
  c1FlexGrid1.Cols[1].DataType = typeof(DateTime);
  //c1FlexGrid1.Cols[1].Format = "yyyy/MM/dd";
  c1FlexGrid1[1, 1] = new DateTime(2019, 5, 1, 0, 0, 0);
  c1FlexGrid1.DrawMode = C1.Win.C1FlexGrid.DrawModeEnum.OwnerDraw;
  c1FlexGrid1.AllowFiltering = true;
}

private void c1FlexGrid1_OwnerDrawCell(object sender, C1.Win.C1FlexGrid.OwnerDrawCellEventArgs e)
{
  if (((e.Col == 1) && (e.Row > 0)))
  {
    if ((e.Text == ""))
    {
      return;
    }
    else
    {
      e.Text = DateTime.Parse(e.Text).ToString("yyyy/MM/dd");
    }
  }
}


【回避方法③】

Formatの値として、"yyyy/MM/dd" の代わりに "d" を設定します。

◎サンプルコード(VB)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
  C1FlexGrid1.Cols(1).Name = "DateTime"
  C1FlexGrid1.Cols(1).WidthDisplay += 100
  C1FlexGrid1.Cols(1).DataType = GetType(DateTime)
  'C1FlexGrid1.Cols(1).Format = "yyyy/MM/dd"
  C1FlexGrid1.Cols(1).Format = "d"
  C1FlexGrid1(1, 1) = New DateTime(2019, 5, 1, 0, 0, 0)
End Sub

◎サンプルコード(C#)
private void Form1_Load(object sender, EventArgs e)
{
  c1FlexGrid1.Cols[1].Name = "DateTime";
  c1FlexGrid1.Cols[1].WidthDisplay += 100;
  c1FlexGrid1.Cols[1].DataType = typeof(DateTime);
  //c1FlexGrid1.Cols[1].Format = "yyyy/MM/dd";
  c1FlexGrid1.Cols[1].Format = "d";
  c1FlexGrid1[1, 1] = new DateTime(2019, 5, 1, 0, 0, 0);
}


【回避方法④】

アプリケーションのカルチャを明示的に"ja-JP"に指定し、そのDateTimeFormatのFullDateTimePatternを "yyyy/MM/dd" に設定します。

◎サンプルコード(VB)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
  ' アプリケーションのカルチャの変更
  Dim cInfo As System.Globalization.CultureInfo = New System.Globalization.CultureInfo("ja-JP")
  cInfo.DateTimeFormat.Calendar = New System.Globalization.GregorianCalendar()
  cInfo.DateTimeFormat.FullDateTimePattern = "yyyy/MM/dd"
  cInfo.DateTimeFormat.DateSeparator = "/"
  Application.CurrentCulture = cInfo

  C1FlexGrid1.Cols(1).Name = "DateTime"
  C1FlexGrid1.Cols(1).WidthDisplay += 100
  C1FlexGrid1.Cols(1).DataType = GetType(DateTime)
  'C1FlexGrid1.Cols(1).Format = "yyyy/MM/dd"
  C1FlexGrid1(1, 1) = New DateTime(2019, 5, 1, 0, 0, 0)
End Sub

◎サンプルコード(C#)
private void Form1_Load(object sender, EventArgs e)
{
  // アプリケーションのカルチャの変更
  System.Globalization.CultureInfo cInfo = new System.Globalization.CultureInfo("ja-JP");
  cInfo.DateTimeFormat.Calendar = new System.Globalization.GregorianCalendar();
  cInfo.DateTimeFormat.FullDateTimePattern = "yyyy/MM/dd";
  cInfo.DateTimeFormat.DateSeparator = "/";
  Application.CurrentCulture = cInfo;

  c1FlexGrid1.Cols[1].Name = "DateTime";
  c1FlexGrid1.Cols[1].WidthDisplay += 100;
  c1FlexGrid1.Cols[1].DataType = typeof(DateTime);
  //c1FlexGrid1.Cols[1].Format = "yyyy/MM/dd";
  c1FlexGrid1[1, 1] = new DateTime(2019, 5, 1, 0, 0, 0);
}



(2019.07.29追記)

GanttView for WinFormsでも、開始日や終了日の表示時に同様の現象が発生することがあります。C1GranttViewコントロールでは、グリッドビューの内部コントロールとしてFlexGridを使用しているためで、同様な手段で回避することができます(回避方法④を除く)。

◆例:回避方法②を使用した場合
※事前に開発画面で、C1GanttViewのコンテキストメニューから「列の編集」を選択し、開始日と終了日のVisible=Trueに設定します。

◎サンプルコード(VB)
Imports C1.Win.C1FlexGrid
Imports C1.Win.C1GanttView

Public Class Form1
  Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    C1GanttView1.GridDateFormat = "yyyy/MM/dd"
    Dim C1FlexGrid1 As C1FlexGrid = CType(C1GanttView1.Controls(2), C1FlexGrid)
    C1FlexGrid1.DrawMode = DrawModeEnum.OwnerDraw
    AddHandler C1FlexGrid1.OwnerDrawCell, New OwnerDrawCellEventHandler(AddressOf C1FlexGrid1_OwnerDrawCell)
  End Sub

  Private Sub C1FlexGrid1_OwnerDrawCell(ByVal sender As Object, ByVal e As OwnerDrawCellEventArgs)
    Dim C1FlexGrid1 As C1FlexGrid = CType(C1GanttView1.Controls(2), C1FlexGrid)
    If (((e.Col = C1FlexGrid1.Cols("開始日").Index) Or (e.Col = C1FlexGrid1.Cols("終了日").Index)) AndAlso (e.Row > 0)) Then
      If (e.Text = "") Then
        Return
      Else
        e.Text = DateTime.Parse(e.Text).ToString("yyyy/MM/dd")
      End If
    End If
  End Sub
End Class

◎サンプルコード(C#)
using C1.Win.C1FlexGrid;
using C1.Win.C1GanttView;

namespace GanttViewDateFormatWorkAround
{
  public partial class Form1 : Form
  {
    public Form1()
    {
      InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
      c1GanttView1.GridDateFormat = "yyyy/MM/dd";
      C1FlexGrid c1FlexGrid1 = c1GanttView1.Controls[2] as C1FlexGrid;
      c1FlexGrid1.DrawMode = DrawModeEnum.OwnerDraw;
      c1FlexGrid1.OwnerDrawCell += C1FlexGrid1_OwnerDrawCell;
    }

    private void C1FlexGrid1_OwnerDrawCell(object sender, OwnerDrawCellEventArgs e)
    {
      C1FlexGrid c1FlexGrid1 = c1GanttView1.Controls[2] as C1FlexGrid;
      if (((e.Col == c1FlexGrid1.Cols["開始日"].Index | e.Col == c1FlexGrid1.Cols["終了日"].Index) && (e.Row > 0)))
      {
        if ((e.Text == ""))
        {
          return;
        }
        else
        {
          e.Text = DateTime.Parse(e.Text).ToString("yyyy/MM/dd");
        }
      }
    }
  }
}