none
標準の DataGridViewCell より大きい UserControl を常時ホストする場合、行の高さや列の幅を調整するには

    質問

  • 下記を参考に DataGridView でホスト可能な Column/Cell を作成してみようと
    試みています。


    (1) 方法 : Windows フォーム DataGridView コントロールのセルと列を、それぞれの動作と外観を拡張してカスタマイズする


    このサンプルや他のサイトなどで紹介されているものは、標準的な
    DataGridViewCell の中にすっぽり入る程度の大きさのものしか挙げられていません。


    今回は、標準的な DataGridViewCell の大きさよりも大きい UserControl をホ
    ストしてみようと考えています。


    とすると気になるのは、どうやって行の高さや列の幅を調整するか、です。


    DataGridViewImageCell は割り当てられているイメージの高さや幅に合わせて、
    行の高さや列の幅が調整されているので、そ
    のソースコードを参考に読みました。

     

    ※ DataGridViewImageColumn/Cell で内包するイメージのサイズに合わせて行
       の高さや列の幅が調整される、という私の認識は間違いでした。明らかに
       Cell よりも大きいイメージを挿入してみたら、標準ではイメージの一部しか Cell
       内に表示されませんでした。

     

    が、どうもよく分かりません。何処で調整されているのかお分かりの方がいらっしゃったら、

    教えていただけませんか? Paint() -> PaintPrivate() の何処かだと思うのですが。

     

    お聞きしたいのは、

     

      新しくホストする Cell から、どうやって行の高さや列の幅を Cell に合わせられるのか、

     

    ということです。お分かりの方がいらっしゃったら、教えていただけませんか。

     

     

     

    ちなみに、UserControl の高さに合わせて Cell.Paint() の定義内で
    Cell.OwningRow.Height を書き換えようとしたら、共有行の Height を触るの
    はよくない旨のメッセージが出てしまいました。
    # このエラーの意味もよく分かりませんが。

     

     

    参考
    (2) Windows Forms Data Controls and Databinding FAQ
    (3) DataGridView に ProgressBar を表示する: .NET Tips: C#, VB.NET, Visual Studio
    (4) Windows Forms Documentation Updates : DataGridView Watermark Cell
    (5) 方法 : Windows フォーム DataGridView Cells でコントロールをホストする

     

    2008年3月2日 21:20

回答

  •  custar さんからの引用
    とすると気になるのは、どうやって行の高さや列の幅を調整するか、です。

    ユーザーが列境界をダブルクリックした場合や、プログラムから DataGridView の
    AutoResize系メソッドを呼び出した場合に、それぞれのセルの内容に合わせて、
    セルを適切なサイズに自動調整させたい、という意味であれば、
     DataGridViewCell.GetPreferredSize
     DataGridViewRow.GetPreferredHeight
     DataGridViewColumn.GetPreferredWidth
    などをオーバーライドすることによって実装可能かと思います。

    http://msdn2.microsoft.com/ja-jp/library/74b2wakt.aspx

     

     custar さんからの引用
    ちなみに、UserControl の高さに合わせて Cell.Paint() の定義内で
    Cell.OwningRow.Height を書き換えようとしたら、共有行の Height を触るの
    はよくない旨のメッセージが出てしまいました。

    データバインドしている場合、各行のスタイルはほぼ同一になりますよね。
    たとえばデータが1000行あった時に、1000行分のインスタンスを個別に作るのは
    効率が悪いので、同じ設定値(スタイルやイベント割り当てなど)を持つ行は、
    「共有行」として、可能な限り使いまわすように設計されています。
    http://msdn2.microsoft.com/ja-jp/library/ha5xt0d9.aspx


     custar さんからの引用
    # このエラーの意味もよく分かりませんが。

    セルの高さが変われば描画エリアも変わりますので、再度 Paint の必要が生じます。
    処理が循環してしまう可能性があるため、Paint からセルサイズを操作すべきでは無いかと。

     

    2008年3月3日 3:07
  •  custar さんからの引用
    常時 UserControl のサイズに合わせた表示にするつもりです。

    たとえば「固定で 50 x 50 にしたい」セルと「固定で 120 x 30 にしたい」セルが、
    同じ行(または同じ列)にあった場合、どちらに合わせるべきとも言えませんよね。

     

    ですから通常、セルのサイズを調整するのは、子(セル側)の仕事としてではなく、
    親によって管理される物になっているかと思います。

     

    「内容に基づいて自動的にサイズ変更するモード」も用意されてはいますが、それとて
    セル側が、親に対して「このぐらいの領域が欲しい」と訴えかけているだけであって、
    セル側が直接、親の高さ/幅を直接コントロールしているわけではありません。

     


     custar さんからの引用
    Cell.Paint() 内部からのサイズ変更だとループになるのならば、視点を変えて、
    大元である DataGridView の CellPainting イベントで調整すべきなのかな?

     

    『描画系の処理』と、『サイズ調整/サイズ測定系の処理』は、それぞれ分けて考えてみてください。


    『サイズ』については、先ほど紹介した Windows フォーム DataGridView コントロールのサイズ変更オプション
    参照してみてください。『内容に基づくサイズ変更動作のカスタマイズ』のあたりが相当するかと。

     

     

     custar さんからの引用
    標準の DataGridViewCell より大きいサイズの UserControl を常時ホストする場合、どうやって行の高さや列の幅を調整するのか

     

    サイズ固定というわけではありませんが、「最小限必要なサイズ」については、

    たとえば、行の MinimumHeight や列の MinimumWidth などが利用できます。

     

    『描画』についてセル側でやるべきことは、親に与えられた領域内に描画するという作業です。
    領域が広すぎれば、余白を作るなり、拡大するなりといった対応になるでしょうし、
    逆に狭すぎれば、たとえばクリッピング/縮小/スクロール表示などを行えば OK かと。

    (たとえばテキスト列だと、狭い幅に対して "..." の省略表記を行うようになっていますね)
    2008年3月3日 7:21

すべての返信

  •  custar さんからの引用
    とすると気になるのは、どうやって行の高さや列の幅を調整するか、です。

    ユーザーが列境界をダブルクリックした場合や、プログラムから DataGridView の
    AutoResize系メソッドを呼び出した場合に、それぞれのセルの内容に合わせて、
    セルを適切なサイズに自動調整させたい、という意味であれば、
     DataGridViewCell.GetPreferredSize
     DataGridViewRow.GetPreferredHeight
     DataGridViewColumn.GetPreferredWidth
    などをオーバーライドすることによって実装可能かと思います。

    http://msdn2.microsoft.com/ja-jp/library/74b2wakt.aspx

     

     custar さんからの引用
    ちなみに、UserControl の高さに合わせて Cell.Paint() の定義内で
    Cell.OwningRow.Height を書き換えようとしたら、共有行の Height を触るの
    はよくない旨のメッセージが出てしまいました。

    データバインドしている場合、各行のスタイルはほぼ同一になりますよね。
    たとえばデータが1000行あった時に、1000行分のインスタンスを個別に作るのは
    効率が悪いので、同じ設定値(スタイルやイベント割り当てなど)を持つ行は、
    「共有行」として、可能な限り使いまわすように設計されています。
    http://msdn2.microsoft.com/ja-jp/library/ha5xt0d9.aspx


     custar さんからの引用
    # このエラーの意味もよく分かりませんが。

    セルの高さが変われば描画エリアも変わりますので、再度 Paint の必要が生じます。
    処理が循環してしまう可能性があるため、Paint からセルサイズを操作すべきでは無いかと。

     

    2008年3月3日 3:07
  •  魔界の仮面弁士 さんからの引用

     custar さんからの引用

    とすると気になるのは、どうやって行の高さや列の幅を調整するか、です。

     

    ユーザーが列境界をダブルクリックした場合や、プログラムから DataGridView
    の AutoResize 系メソッドを呼び出した場合に、それぞれのセルの内容に合わ
    せて、セルを適切なサイズに自動調整させたい、という意味であれば、


    常時 UserControl のサイズに合わせた表示にするつもりです。


    イメージのサイズに合わせて Cell のサイズを変更するとして、それを行の高
    さ、列の幅にどう反映させれば良いのか、分かりません。


    勝手に FillRectangle() で Cell の領域を塗りつぶしたとしても、それは
    Cell の勝手な行動で、Column や Row にはそれが反映されないように思えてい
    ます。


    どうやるのかなぁ?


     魔界の仮面弁士 さんからの引用

     custar さんからの引用

    ちなみに、UserControl の高さに合わせて Cell.Paint() の定義内で
    Cell.OwningRow.Height を書き換えようとしたら、共有行の Height を触るの
    はよくない旨のメッセージが出てしまいました。


    データバインドしている場合、各行のスタイルはほぼ同一になりますよね。た
    とえばデータが 1000行あった時に、1000行分のインスタンスを個別に作るのは
    効率が悪いので、同じ設定値(スタイルやイベント割り当てなど)を持つ行は、
    「共有行」として、可能な限り使いまわすように設計されています。


    なるほど。下記ドキュメントを読んで解せなかったのですが、ご説明から大凡
    (おおよそ) 分かりかけてきました。


    - Windows フォーム DataGridView コントロールを拡張するための推奨される手順
    ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.ja/dv_fxmclictl/html/8321a8a6-6340-4fd1-b475-fa090b905aaf.htm

     

     魔界の仮面弁士 さんからの引用

     custar さんからの引用

    # このエラーの意味もよく分かりませんが。


    セルの高さが変われば描画エリアも変わりますので、再度 Paint の必要が生じ
    ます。処理が循環してしまう可能性があるため、Paint からセルサイズを操作
    すべきでは無いかと。


    ご指摘ありがとうございます。言われてみれば、そうですね。ループするでしょう。

     

    Cell.Paint() 内部からのサイズ変更だとループになるのならば、視点を変えて、
    大元である DataGridView の CellPainting イベントで調整すべきなのかな?

     

     

    ※ タイトルを変更します。

    (前) DataGridViewImageCell はどうやって行の高さや列の幅を調整しているのか

    (後) 標準の DataGridViewCell より大きいサイズの UserControl を常時ホストする場合、どうやって行の高さや列の幅を調整するのか

    2008年3月3日 4:29
  •  custar さんからの引用
    常時 UserControl のサイズに合わせた表示にするつもりです。

    たとえば「固定で 50 x 50 にしたい」セルと「固定で 120 x 30 にしたい」セルが、
    同じ行(または同じ列)にあった場合、どちらに合わせるべきとも言えませんよね。

     

    ですから通常、セルのサイズを調整するのは、子(セル側)の仕事としてではなく、
    親によって管理される物になっているかと思います。

     

    「内容に基づいて自動的にサイズ変更するモード」も用意されてはいますが、それとて
    セル側が、親に対して「このぐらいの領域が欲しい」と訴えかけているだけであって、
    セル側が直接、親の高さ/幅を直接コントロールしているわけではありません。

     


     custar さんからの引用
    Cell.Paint() 内部からのサイズ変更だとループになるのならば、視点を変えて、
    大元である DataGridView の CellPainting イベントで調整すべきなのかな?

     

    『描画系の処理』と、『サイズ調整/サイズ測定系の処理』は、それぞれ分けて考えてみてください。


    『サイズ』については、先ほど紹介した Windows フォーム DataGridView コントロールのサイズ変更オプション
    参照してみてください。『内容に基づくサイズ変更動作のカスタマイズ』のあたりが相当するかと。

     

     

     custar さんからの引用
    標準の DataGridViewCell より大きいサイズの UserControl を常時ホストする場合、どうやって行の高さや列の幅を調整するのか

     

    サイズ固定というわけではありませんが、「最小限必要なサイズ」については、

    たとえば、行の MinimumHeight や列の MinimumWidth などが利用できます。

     

    『描画』についてセル側でやるべきことは、親に与えられた領域内に描画するという作業です。
    領域が広すぎれば、余白を作るなり、拡大するなりといった対応になるでしょうし、
    逆に狭すぎれば、たとえばクリッピング/縮小/スクロール表示などを行えば OK かと。

    (たとえばテキスト列だと、狭い幅に対して "..." の省略表記を行うようになっていますね)
    2008年3月3日 7:21
  •  魔界の仮面弁士 さんからの引用

     custar さんからの引用

    常時 UserControl のサイズに合わせた表示にするつもりです。


    たとえば「固定で 50 x 50 にしたい」セルと「固定で 120 x 30 にしたい」セ
    ルが、同じ行(または同じ列)にあった場合、どちらに合わせるべきとも言えま
    せんよね。


    ですから通常、セルのサイズを調整するのは、子(セル側)の仕事としてではな
    く、親によって管理される物になっているかと思います。


    なるほど。


    現在の UserControl は全てのセルで同じサイズという前提ですが、もっと先に
    は個々に変更する予定ですから、留意すべきですね。


     魔界の仮面弁士 さんからの引用

    「内容に基づいて自動的にサイズ変更するモード」も用意されてはいますが、
    それとてセル側が、親に対して「このぐらいの領域が欲しい」と訴えかけてい
    るだけであって、セル側が直接、親の高さ/幅を直接コントロールしているわけ
    ではありません。


    分かりやすい。了解。


     魔界の仮面弁士 さんからの引用

    『描画系の処理』と、
    『サイズ調整/サイズ測定系の処理』は、
    それぞれ分けて考えてみてください。

     

    『サイズ』については、先ほど紹介した Windows フォーム DataGridView コン
    トロールのサイズ変更オプション を参照してみてください。『内容に基づくサ
    イズ変更動作のカスタマイズ』のあたりが相当するかと。


    ありがとうございます。

     

     魔界の仮面弁士 さんからの引用

    サイズ固定というわけではありませんが、「最小限必要なサイズ」については、
    たとえば、行の MinimumHeight や列の MinimumWidth などが利用できます。


    ふむ。


     魔界の仮面弁士 さんからの引用

    『描画』についてセル側でやるべきことは、
    親に与えられた領域内に描画するという作業です。


    この役割分担には気をつけます。


    では、早速教えてもらった情報を元にまた調査します。
    魔界の仮面弁士 さん、ありがとうございます。

     

    DataGridView ..... セルのサイズ調整
    Cell ............. 親に与えられた領域内への描画

    2008年3月3日 8:20
  • こんにちは。中川俊輔 です。

     

    魔界の仮面弁士さん、回答ありがとうございます。

     

    custarさん、フォーラムのご利用ありがとうございます。

    有用な情報と思われたため、魔界の仮面弁士さんの回答へ回答済みチェックをつけさせていただきました。

     

    回答済みチェックが付くことにより、有用な情報を探している方が情報を見つけやすくなります。
    有用な情報と思われる回答があった場合は、なるべく回答済みボタンを押してチェックを付けてください。

    custarさんはチェックを解除することもできますので、ご確認ください。

     

    それでは!

     

    2008年3月21日 9:24