DOBON.NET DOBON.NETプログラミング掲示板過去ログ

DataGridの行の高さを文字列にあわせて設定する

環境/言語:[VB.NET XP]
分類:[.NET]

DataGridで文字列にあわせて行毎に高さを変更する方法は
ないでしょうか?
宜しくご教授願います。
DataGridはWindowsフォームの方で良いですか?

だとすれば、一度普通にDataGridを表示した後、次のリンク先を参考にして、個別に行の高さを変えることによってできるかもしれません。

DataGridの特定の行の高さ変更
http://dobon.net/vb/bbs/log3-9/5107.html#5130
trapemiyaさん、ありがとうございます。
レス遅くなりまして申し訳ございません。

Windowsフォームです。
リンク先参考に四苦八苦しながら試してみました。
しかし、恥ずかしながらどこに追加して、どのように呼べばよいのか
わかりませんでした。
お叱りの言葉を覚悟で伺います。
どのように使用したらよいのでしょうか?
> お叱りの言葉を覚悟で伺います。

おこりませんよ。(^^

> どのように使用したらよいのでしょうか?

リンク先のSetRowHeightはプロシージャなので、引数に高さを変更したい行番号と、その行の高さを指定して呼び出してあげれば良いです。
とりあえずテスト的に、コマンドボタンのボタンクリックイベントプロシージャから呼び出してみたら感覚がつかめるでしょう。
例えば3行目を50の高さにするのであれば、
SetRowHeight(2, 50)
となります。

上のテストがうまくいけば、DataGridの全ての行をSetRowHeightプロシージャを使って、行高を設定してあげれば良いと思います。これを行うタイミングとしては、DataGridにデータソースをバインドした後でいいのではないでしょうか?
ただ、行高を設定しても、その中で文字列を折り返して表示するとなると、また、別の問題になります。
trapemiyaさん、申し訳ございませんm(__)m
丁寧に教えて頂いたのに、未だに解決していません。

テスト用のFormにDataGridを1つ、Buttonを1つを作成し
SetRowHeightプロシージャを呼んでみたのですが、
GetValueで【オブジェクトがターゲットの型と一致しません。】
となってしまいます。
2006/05/16(Tue) 12:14:11 編集(投稿者)

お〜、すみません。リンク先のコードは、DataGridを継承したクラスで使うように
組まれてました。invalidateやMeがある段階で気付くべきでした。大変すみません。
ごめんなさい。m(_ _)m
で、それを継承したクラスではなく、普通にDataGridをターゲットにして行の高さを
変更するパターンを以下に示します。すみません、VB.NETは詳しくないので、
C#に変換して書いてしまいました。

public void SetRowHeight(DataGrid dgt, int Row, int height) 
{ 
    try 
    { 
        PropertyInfo p = typeof(DataGrid).GetProperty("DataGridRows", 
            BindingFlags.FlattenHierarchy | BindingFlags.IgnoreCase |
            BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public |
            BindingFlags.Instance | BindingFlags.Static); 

        object[] r = (object[])p.GetValue(dgt, BindingFlags.Instance | BindingFlags.Static |
             BindingFlags.GetProperty | BindingFlags.Public |
             BindingFlags.SuppressChangeType, null, null, null); 

        if (Row < r.Length) 
        { 
            Type drt = dgt.GetType().Assembly.GetType("System.Windows.Forms.DataGridRow");
            drt.GetProperty("Height").SetValue(r[Row], height, null); 
        } 
        else 
        { 
            throw new Exception("Row index outside of boundaries."); 
        } 
    } 
    catch(Exception e)
    { 
        MessageBox.Show(e.Message);
    } 
}

以下、コンバートツールによってVB.NETにコンバートしたコードです。

Public Sub SetRowHeight(dgt As DataGrid, Row As Integer, height As Integer)
   Try
      Dim p As PropertyInfo
            = GetType(DataGrid).GetProperty("DataGridRows", BindingFlags.FlattenHierarchy Or
                BindingFlags.IgnoreCase Or BindingFlags.Instance Or BindingFlags.NonPublic Or
                BindingFlags.Public Or BindingFlags.Instance Or BindingFlags.Static)
      
      Dim r As Object()
            = CType(p.GetValue(dgt, BindingFlags.Instance Or BindingFlags.Static Or
                BindingFlags.GetProperty Or BindingFlags.Public Or BindingFlags.SuppressChangeType,
                Nothing, Nothing, Nothing), Object())
      
      If Row < r.Length Then
         Dim drt As Type = dgt.GetType().Assembly.GetType("System.Windows.Forms.DataGridRow")
         drt.GetProperty("Height").SetValue(r(Row), height, Nothing)
      Else
         Throw New Exception("Row index outside of boundaries.")
      End If
   Catch e As Exception
      MessageBox.Show(e.Message)
   End Try
End Sub 'SetRowHeight

SetValueとか使わずに、VB.NETでは元のままの表記で動くかもしれませんね。
いずれにしても上記を参考にしてトライしてみてください。
trapemiyaさん、誤らないでください。
私が勉強不足名だけですから!
申し訳ないですm(__)m
ソースコードまでつけて頂いて本当にありがとうございます。

早速、試してみて、動作確認できました。
でも、やはり高さは指定しなければだめですよね・・・。
セルに表示されている行数は一行毎に異なるので、高さもそれに従い
異なってきます。

セル内の文字列の行数を取得する方法などご存じないでしょうか?
> セル内の文字列の行数を取得する方法などご存じないでしょうか?

改行コードを数えれば良いのではないでしょうか?vbCrLf、または、ControlChars.CrLfを数えれば行数がわかると思います。
また、
drt.GetProperty("Height").SetValue(r(Row), Nothing)
で、その行の高さが取れますので(上のコードでIntegerにキャストが必要かもしれません)、それに行数を掛け合わせれば良いと思います。
■No15793に返信
trapemiyaさん返信ありがとうございます。
当方の都合により作業が中断させられており、試すのが遅くなってしまい
レスが大変遅くなってしまいました。
本当に申し訳ございません。

本日、やっと動作確認できました♪
セルの中で文字列の折り返しもしているので、改行コードの数とCrLfの前まで
の文字数を取得し、折り返した場合の行数とで算出しました。
各行、文字列にあわせて高さを設定することができました。
ありがとうございました。

ここまでご指導いただき、さらにとは甘えすぎだとは承知しておりますが
最後にもうひとつだけお聞きしてもよろしいでしょうか?

まだまだDataGridに機能を追加しなくてはならないようで、ユーザーコントロール
を作成することになると思われるのですが、SetRowHeightはユーザーコントロール
でも使えるのでしょうか?
> 最後にもうひとつだけお聞きしてもよろしいでしょうか?

私がわかる範囲内でしたらいくらでもお答えしますので、遠慮されなくてもいいですよ。それに、私にとっても勉強になりますし。(^^

> を作成することになると思われるのですが、SetRowHeightはユーザーコントロール
> でも使えるのでしょうか?

SetRowHeightなどの機能を追加するためにユーザーコントロールやカスタムコントロールは存在しているようなものなので、大丈夫ですよ。
■No15943に返信
trapemiyaさんのありがとうございます。
なんとお礼を言えばいいのかm(__)m
今まで、VB6.0を多少使っていた程度で、.NETは全くの初心者です。
社内で唯一のプログラム経験者なので、他に教えを請える人間もいませんし。。。
うれしくって目頭が熱くなってしまいました。

お言葉に甘えてすみません。

今まで動作確認はテスト環境で行っていたのですが、本番環境に摘要したときに
『オブジェクト参照がオブジェクトインスタンスに設定されていません』
というメッセージが表示されてしまいます。
テスト環境と本番環境との違いは
http://dobon.net/vb/dotnet/datagrid/lockcolumnwidth.html
のDataGridの列の幅をユーザーが変更できないようにしているだけです。
> うれしくって目頭が熱くなってしまいました。

おおげさですよぉ(^^

> 『オブジェクト参照がオブジェクトインスタンスに設定されていません』
> というメッセージが表示されてしまいます。
> テスト環境と本番環境との違いは
> http://dobon.net/vb/dotnet/datagrid/lockcolumnwidth.html
> のDataGridの列の幅をユーザーが変更できないようにしているだけです。

本番系の環境の問題ではないと思います。疑わしきはプログラムの方です。
エラーが発生した時に詳細ボタンを押すと、何行目でエラーが発生しているのかがわかりますから、CTRL + Gでその行数を入れて、その行にジャンプしてみてください。そこで使われているオブジェクト変数に、何か代入し忘れているのでないかと思います。
■No15997に返信
trapemiyaさんの何度も丁寧な返信ありがとうございます。
自分で解決できないものにこだわる必要があるのか、疑いつつ
やはり、四苦八苦悶絶しております。

DataGridの派生クラス『MyDataGrid』を作成し、そのDataGridに対し
SetRowHeightを呼んでいるのですが

Dim drt As Type = dgt.GetType().Assembly.GetType("System.Windows.Forms.DataGridRow") drt.GetProperty("Height").SetValue(r(Row), height, Nothing)

この時、drt = Nothing で
『オブジェクト参照がオブジェクトインスタンスに設定されていません』
となってしまいます。
派生クラスに対してでなければ、エラーは発生しません。

未熟者がなんでもかんでも機能を追加しようとしていることに
間違いがあるのでしょう・・・・・・・ね
> 自分で解決できないものにこだわる必要があるのか、疑いつつ
> やはり、四苦八苦悶絶しております。

バグや仕様などのように本質的でないものに関しては、できるだけこだわった方が良いと私は思います。ただ、こだわり過ぎていつの間にか本流から外れて支流にいるのに気付かないということになると、自分にとってマイナスです。
本流の中で、時間が許す範囲内で、こだわれることはこだわった方がいいと思います。

> 派生クラスに対してでなければ、エラーは発生しません。

どのタイミングで行の高さを変更しているのかがわかりませんが、まだ派生クラスのインスタンスが作成されていないということはないでしょうか?
また、アセンブリの関係があるのかもしれません。一度派生クラスを含めた形でとりあえずコンパイルを通しておいて、そこでもう一度試してみたらどうなるでしょうか?
■No16041に返信
trapemiyaさん、すぐに返信できずに済みませんでした。
調査に時間がかかってしまいました。

> どのタイミングで行の高さを変更しているのかがわかりませんが、まだ派生クラスのインスタンスが作成されていないということはないでしょうか?

抽出の範囲を指定し、ボタンが押されたところでDataGridのDataSourceをセット
SetRowHeightの実行という流れです。
派生クラスのインスタンスを上の処理の前で行ってもエラーが発生します。

アセンブリのところで『Nothing』が返されているので、そこの問題のようです。

いろいろと調べてはいるのですが、まだ解決にたどり着けそうにありません・・・(;-_-A
自己レスです。

Dim drt As Type = dgt.GetType().Assembly.GetType("System.Windows.Forms.DataGridRow")
drt.GetProperty("Height").SetValue(r(Row), height, Nothing)

r(Row).height=height
に変更しましたところ、動作確認が取れました♪
やはり、アセンブリのところだったようです(;^_^A

長々とお付き合い頂き、本当にありがとうございましたm(_ _)m
■No16070に返信(UNさんの記事)
うかれて、解決済みにチェックするのを忘れてしまいました。
失礼しました。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板