none
DataGridView で DateTimePicker を表示できたりできなかったり RRS feed

  • 全般的な情報交換

  • 下記情報を参考に DataGridView 上に DateTimePicker を表示させようとして
    います。

     

    - 方法 : Windows フォーム DataGridView Cells でコントロールをホストする
    http://msdn2.microsoft.com/ja-jp/library/7tas5c80(VS.80).aspx

     

    現状、DataGridView のセル上に DateTimePicker を表示できたりできなかった
    りしています。何が原因かお分かりになる方、教えていただけませんか。以下
    に、手順と動画を示します。

     

    まず、上記参考ページのコードを使って CalendarColumn というクラスを用意
    し、ファイル CalendarColumn.cs としてソリューションに追加しておきます。

     

    A. 表示できたやり方
    ----
    (1) DataGridView コントロールを Form 上に配置
    (2) DataGridView にコラムを1つ追加
    (3) そのコラムを CalendarColumn に結びつける

     

    これで実行すると、セルに今日の日付が入り、それをクリックすると
    DateTimePicker が表示され、日付を選択できます。

     

    B. 表示できなかったやり方
    ----
    (1) 下記構造のテーブルを用意 (primary key: id)

     

    id int not null
    name varchar(50) not null
    registered datetime not null

     

    (2) このテーブルのデータセットを Form にドラッグ&ドロップして DataGridView を作成
    (3) registered フィールドに CalendarColumn を割り当てる

     

    これで実行すると、registered セルには今日の日付は入っているのですが、ク
    リックすると日付が消えて例外が発生します。

     

    メッセージの内容とデバッガからの情報を見ると、registered セルが空欄であ
    るのがよくない感じがしています。A. では CalendarColumn を割り当てたセル
    の日付は消えませんでしたが、B. の CalendarColumn を割り当てたセルの日付
    はクリックした瞬間に消えています。


    最初の日付の状態から、クリック後の状態に日付情報をコピーしなければなら
    ないのでしょうが、その間でコピーが正しく行われておらず、日付が空白になっ
    ているのかな?と思っていますが、もしそうなら、どうやったたら解決するの
    かが分かりません。

     

    データセットとくっ付いている DataGridView がクリックされた瞬間にセルを
    操作しているようにも見えています。本当はどうか分かりません。

     

    例外が発生する時の様子を動画にしていますので、下記 URL でご確認ください。

     

    URL http://custar.s151.xrea.com/videos/calendarcolumn/calendarcolumn.html


    環境
    (C# 2008 Express Edition 英語版)   + (SQL Server 2005 Express Edition 日本語版)

     

    C# 2008 英語版を使ったのは、C# 2005 日本語版でも同じ現象となったので、
    2008 では改善されたかな、と期待して使ってみたまでです。

    2007年12月4日 9:38

すべての返信

  • データベース (DataSet) 内に記録されている DateTime がセル上に表示されて
    いれば、クリック時に DateTimePicker が正常表示されます。

     

    問題なのは、未設定のセルをクリックした時に、デフォルトで表示されている
    DateTime.Now の値 (日時) が何かしらによって消されてしまうことです。

     

    消されているというよりは、空白のセルになった時に、元々表示されている日
    時を空白セルにコピーできていない、というべきかも知れません。

     

    選択されている時に日時が表示されていれば、おそらく正常に
    DateTimePicker が表示されると思います。


    で、「元々表示されている日時を空白セルにコピー」という作業をどう記述す
    ればよいのか全く分かりません。どなたかお分かりになりませんか?

     

    .net framework のソースがあれば探り当てられるかもしれないのですけど。


    CalendarColumn.cs の一部を以下のようにすれば、例外は発せられません。
    ちなみに CalendarColumn.cs は下記サンプルを用いています。

     

    URL http://msdn2.microsoft.com/ja-jp/library/7tas5c80(VS.80).aspx

     

    コード ブロック

    public override void InitializeEditingControl(int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
    {

      // Set the value of the editing control to the current cell value.
      base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle);
      CalendarEditingControl ctl = DataGridView.EditingControl as CalendarEditingControl;

     

      if (this.Value.ToString() != "")  <----- この if() を追加
      {
        ctl.Value = (DateTime)this.Value;
      }
    }

     

    未設定セルをクリックした時には上記メソッドの引数 initialFormattedValue
    が空白になっているのです。これが "2007/12/11 00:00:00" のような
    DateTime 形式なのが正常です。

     

    空白の this.Value を DateTime にキャストしようとしているので、例外が出
    ていると思います。

     

    空白にしてしまったのはどいつだ!?

    2007年12月11日 7:39
  • 下記では案の定空白時の処理をしてますね。

    .net ではこう書くのか。

     

    コード ブロック

    http://www.krugle.org/kse/files/archive/codeplex.com/dmaide/QuickPIM/QuickPIM/DataGridViewCalendarColumn.cs#2

     

    public override void InitializeEditingControl(int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
    {
      // Set the value of the editing control to the current cell value.
      base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle);
      CalendarEditingControl ctl = DataGridView.EditingControl as CalendarEditingControl;

     

      if (this.Value != DBNull.Value && this.Value != null)
      {
        ctl.Value = Convert.ToDateTime(this.Value);
      }
    }

     

    2007年12月11日 17:07
  • コード ブロック

    CalendarCell

    (click-1)

    ??? ............... 選択状態

    (click-2)

    InitializeEditingControl()

    DateTimePicker .... 編集状態

     

    という流れになっていると思うのだが、
    click-1 後の「選択状態」を管理しているオブジェクトは何なのだろう?

    2007年12月14日 3:37
  • RowEnter の EventHandler で CalendarCell の初期値として DateTime.Now を設定すれば、
    focus された時に日付が消えることはない。
    よって、上記 Exception は出なくなる。

    もっと良い方法があるかもしれない。
    2007年12月17日 4:01
  • Nullを許容するDateTimePickerコントロール

    null でも動く DateTimePicker のようだが、
    本件では始めっから null  にならなきゃいいのに。
    2007年12月19日 7:05
  • - 空白の DataGridViewImageCell に何も表示させたくない - MSDN フォーラム

     

    上記で得たことをヒントに CalendarColumn/Cell を見直してみました。

     

    案の定、表示直後の CalendarCell および新規行の CalendarCell で日付が表
    示されるようになりました。

     

    間違ったことをしていたら、詳しい方、ご指摘ください。

    # 長い回り道だったなぁ。

     

    コード ブロック

    public class CalendarColumn : DataGridViewColumn
    {
      public CalendarColumn() : base(new CalendarCell())
      {
        this.DefaultCellStyle.NullValue = DateTime.Now.ToShortDateString();
      }

     

    ついでに、上記追加で下記 this.Value の if 文は不要になりました。

     

    コード ブロック

    public class CalendarCell : DataGridViewTextBoxCell
    {
      public override void InitializeEditingControl(
        int rowIndex,
        object initialFormattedValue,
        DataGridViewCellStyle dataGridViewCellStyle)
      {
        base.InitializeEditingControl(

          rowIndex, initialFormattedValue, dataGridViewCellStyle);

        CalendarEditingControl

          ctl = DataGridView.EditingControl as CalendarEditingControl;

     

        //if (this.Value != null && this.Value != DBNull.Value)
        //{

          ctl.Value = (DateTime)this.Value;
        //}
      }

     

    2008年1月11日 6:56