質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Windows Forms

Windows Forms(WinForms)はMicrosoft .NET フレームワークに含まれる視覚的なアプリケーションのプログラミングインターフェイス(API)です。WinFormsは管理されているコードの既存のWindowsのAPIをラップすることで元のMicrosoft Windowsのインターフェイスのエレメントにアクセスすることができます。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

Q&A

解決済

1回答

6051閲覧

C#/DataGridViewに西暦1年1月1日を入れると空欄になるのはなぜでしょうか

backyard

総合スコア534

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Windows Forms

Windows Forms(WinForms)はMicrosoft .NET フレームワークに含まれる視覚的なアプリケーションのプログラミングインターフェイス(API)です。WinFormsは管理されているコードの既存のWindowsのAPIをラップすることで元のMicrosoft Windowsのインターフェイスのエレメントにアクセスすることができます。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

0グッド

2クリップ

投稿2018/08/21 02:00

編集2018/08/21 02:24

質問内容

C#のWindows Formsアプリで、DataGridViewにSQL Serverから持ってきたDate型の情報をDataSource設定で表示したところ、0001/01/01(西暦1年1月1日)の場合だけそのセルが空欄になってしまいます。この理由についてご存知の方いらっしゃいましたら教えてください。後述のようにDefaultCellStyleでフォーマットをがっちり指定すれば問題が出ないようですが、なぜそうなるのかが分からず気持ち悪いので質問させていただいた次第です。

別段業務などで困っているわけではないので緊急ではありません。

環境は下記の2つで試しました。いずれも結果は同じです。

  • .NET Framework 4.0、Visual Studio 2010
  • .NET Framework 4.6.1 Visual Studio 2017

試したこと、回避方法

  • DBから戻ってきたDataSet/DataTableのDataRowには値は入っていました。
  • デバッグモードでセルのプロパティを見ていくと、情報として0001/01/01 00:00:00は保持しているようです(表示の問題っぽい)
  • 0001/01/02であれば問題なく表示されます。
  • 0001/01/01 00:00:01であれば問題なく表示されます(0秒だと表示されない)
  • DataGridViewのセルに対して、DefaultCellStyle.Formatで「yyyy/MM/DD HH:mm:ss」を指定すると年月日時分秒問わず問題なく表示されます。

サンプルソースコード

SQL Server 2017からデータを持ってきています。実際はテーブルから取ってきているのですが、ここではサンプル用に無理やりDate型データを作って返しています。末尾の書式設定行を有効にすると問題は起きないのですが、書式設定なしだと1年1月1日の00:00:00だけ空欄になってしまいます。

C#

1 private void buttonShow_Click(object sender, EventArgs e) 2 { 3 // データベースから持ってきたDate型の情報をDataGridViewにデータバインドして表示する際に 4 // 0001/01/01の場合だけ空欄になる(0001/01/02や、0001/01/01 00:00:01は表示される。0001/01/01 00:00:00だけダメ) 5 6 SqlCommand cmd = new SqlCommand(); 7 DataSet ds = new DataSet(); 8 using (SqlDataAdapter adapter = new SqlDataAdapter()) 9 { 10 cmd.Connection = new SqlConnection("Data Source=TESTSERVER;Initial Catalog=test;User ID=test;Password=test"); 11 cmd.CommandText = 12 @"declare @tmp date; 13 set @tmp='0001/01/01'; 14 select @tmp as 西暦;"; 15 adapter.SelectCommand = cmd; 16 adapter.Fill(ds); 17 } 18 19 // DBから持ってきたデータを設定する 20 mainGrid.DataMember = ds.Tables[0].TableName; 21 mainGrid.DataSource = ds; 22 23 // この書式設定を行うと 0001/01/01 00:00:00 も表示されるが、設定しないと空欄になる(←この理由を知りたい) 24 // mainGrid.Columns[0].DefaultCellStyle.Format = "yyyy/MM/dd HH:mm:ss"; 25 }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

データソースの型をDateTime型とし、値をDateTime.MinValueとすると空白表示される。
そのCellのFormattedValueがすでにstring.Emptyとなっている。

Frameworkのソースを読むと、FormattedValueを得るとき、DateTime.ToStringではなくSystem.ComponentModel.DateTimeConverterを使用してstring型に変換している。
このSystem.ComponentModel.DateTimeConverterを使用してDateTime.MinValueをstringに変換すると
確かにstring.Emptyとなる。

C#

1Console.WriteLine(TypeDescriptor.GetConverter(typeof(DateTime)).ConvertToString(DateTime.MinValue));

DateTimeConverterにてMinValueの時はstring.Emptyを返すよう実装されていました。

compmod\system\componentmodel\DateTimeConverter.cs

C#

1 public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { 2 if (destinationType == typeof(string) && value is DateTime) { 3 DateTime dt = (DateTime) value; 4 if (dt == DateTime.MinValue) { 5 return string.Empty; 6 } 7 8以下略

ですので、質問者さんが挙げておられる回避策などでデフォルトの変換を行わないようにするしかないと思われます。

ちなみに、style.Formatを指定した場合はTostring(style.Format,style.FormatProvider)で変換されるようです。

投稿2018/08/21 12:23

編集2018/08/21 12:49
YAmaGNZ

総合スコア10489

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

backyard

2018/08/22 01:51

ありがとうございます。Visual Studioで.NET Framework自体のデバッグを行い、コンバーターとしてDateTimeConverterが選択されるところまで確認できました。またDateTimeConverterのソースもありがとうございます。 というわけで、原因は「仕様」、回避法は「明示的に書式を設定する」ということですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問