[C#] DateTimePickerでの空表示について

.NETの仕事のバグ修正依頼が来た。Windows7ではエラーになるという。
作成当時はWindows7はなかったし、保守期間は終わっているので無料で修正というわけでもないので、修正すること自体は問題はないのですが..自分が作ったわけでもないので調査していくことにしました。

 

 よーく調べてみるとDateTimePickerに問題があることが発覚。DateTimePickerというのは必ず値を持つのが仕様のようです。入力必須ではない項目にDateTimePickerを使用しているため、入力なしの状態を行うためのハックがしてありました。

 

仕様の段階で本来別のコントロールなりを使うべきか判断をするのでしょうが、見た目上正しく動いていることで正式にリリースされていました。
このハックの方法がどういうものかというと、カスタムフォーマットにてその形式で選択した年月日が表示されますがそのフォーマットを変えることによって見た目何も表示されないように見えるというものです。

 

「なし」の状態の時にはカスタムフォーマットに”g”を指定するという方法です。「DateTimePicker 空」とかでググルといろいろ出て来ますが、このハックを提示しているところは少ないようです。

 

コード的には

this.dateTimePicker1.Format = System.Windows.Forms.DateTimePickerFormat.Custom;
this.dateTimePicker1.CustomFormat = "g";

のように設定しておいて

dateTimePicker1.CustomFormat = "MM/dd/yyyy";

dateTimePicker1.CustomFormat = "g";

を適時切り替えて表示を消すということ。

 

これの何が問題かというとまず

DateTimePickerのCustomFormatのプロパティでは

DateTimePicker.CustomFormat Property

にあるように、有効な書式に”g”は存在しない。という時点でコードとしては正しくないのです。

※これ カスタムの日付と時刻の書式指定文字列 と混同してはいけない

正しくないことをしていては、OSや.NETフレームワークのバージョンが違っても常に同じ動作になることを期待はできない。

 

次にカスタムフォーマットでの表示での文字列(.Textプロパティ)を得て「なし」の状態か判断していること。

xpでやると”g”に変えてたまたまクリアされたような見た目になりますが、7だと”西暦”の文字が表示されます。

※いまのところこの動作になるOSや.NETフレームワークのバージョンは正確に把握はしていません

 

つまりCustomFormat=”g”とするとたまたま動作として年代のみというフォーマットが効いてしまい(なぜ効くのかはバグなのかどうだかわからないが).Textで判断してしまうと明らかに違う動きになってしまいます。

本来「なし」かどうかというのはValueにて値で判断するものであって、表示で判断するのもおかしな話です。

 

でどうすればいいかというと、DateTimePickerのままで行くとする場合こういうのを見つけました。

Nullを許容するDateTimePickerコントロール

これなら値として「なし」かどうか確実に判断ができますね。

 

このままだと「なし」のときカレンダーがでると古い年が出てきてしまうので

protected override void OnDropDown(EventArgs e)
{
    if (_isNull)
    {
        this.Value = DateTime.Today;
    }
    base.OnDropDown(e);
}

を加えるとよさげです。

 

趣味とか出なく仕事でやるばあいは、ネットにはいろんな情報が転がっていますがコピペで何も考えずに使うのは論外。動作だけ見てどんな処理をしているのかきちんと把握しないで使うのもなしですよね。

 

もしこのような方法を使っていたという人は、このようなバグに遭遇するかもですのでお気をつけください。

 

あくまでもプログラマ仕事上の心得や、コードの注意喚起の情報のための記事であり仕事の愚痴などではありません。

カテゴリー: .NET タグ: ,

関連してるかも記事

この記事へのコメント

※コメントはスパム対策の為、承認制となっています。あらかじめご了承ください。

トラックバックURL