none
DataGridのカラム幅自動調整後の処理 RRS feed

  • 質問

  • はじめて利用させていただきます。

    SV2010 .Net4 C#にて開発しております。

    DataGridにてカラム幅を自動調整後、自動調整の状態を解除する方法が分かりません。

    自動調整する際には

    DataGridColumnHeader.Column.Width = DataGridLength.Auto;

    とし、これによりカラム幅が調整されます。

    このままだと自動調整され続けてしまうため、設定後自動調整を中止したく

    WidthにそのカラムのActualWidthを設定するとまだそれには幅が設定されていないようで適切な幅になりませんでした。

    どのように設定すればよいのかご教授お願いします。

     

    2011年6月3日 6:59

回答

  • すみません、
    DataGridColumnHeader.Widthプロパティと見間違いをしていました。
    ごめんなさい。

    それで、試してみて欲しいのですが
    header.Column.Width = DataGridLength.Auto;
    と、
    header.Column.Width = header.Column.ActualWidth;
    の間に

    dataGrid.UpdateLayout();
    を挟むとどうなりますか?

    # UIElement.UpdateLayout メソッド (System.Windows)
    # http://msdn.microsoft.com/ja-jp/library/system.windows.uielement.updatelayout(v=VS.100).aspx

    • 回答としてマーク たう 2011年6月9日 10:48
    2011年6月8日 9:01
  • Width を変更した後、実際にレイアウトパスが実行される(で、各セルの中身の長さが測定され最終的に列幅が決定され ActualWidth が実際の値を返すようになる)のは少し後のタイミングになりますからね。

    UpdateLayout を呼び出すことでレイアウトパスの実行を強制させることができます。その後 ActualWidth を取得する、というのが一つ。

    逆にレイアウトパスの実行まで待つという観点から、Dispatcher.BeginInvoke で ActualWidth の取得を行うというのが一つ(もちろん、DispatcherPriority.Render よりも低い優先順位で)。

    • 回答としてマーク たう 2011年6月9日 10:48
    2011年6月8日 9:09

すべての返信

  • こんにちは。

    普通に可能なはずですけど、どういう風に(どの場所に等)書いていますか?

    「幅が設定されていない」は何をもってそう判断しましたか?

    もう少し詳しく書いていただけると、回答がつきやすいと思います。

    よろしくお願い致します。

     

     

    2011年6月3日 9:34
  • 返信が遅くなってすみません。

    エクスプローラのカラムヘッダーのメニューと同じような機能を実装しようとしています。

    以下は、エクスプローラの「すべての列のサイズを自動的に変更する」のイメージです。

    カラムヘッダにメニューを表示させて、そのメニューのクリックイベントで

    foreach (DataGridColumn col in dataGrid.Columns)
    {
        col.Width = DataGridLength.Auto;
        col.Width = col.ActualWidth;
    }
    としています。

    こうするとすべてのカラムで「ActualWidth=20」になってしまいます。

    よろしくお願いします。

    2011年6月6日 1:52
  • こんにちは。

    いまいち質問の意味が理解できているか自信が無いですが、
    最初の質問文では
    DataGridColumnHeader
    のColumn.Widthを設定していますよね。

    次の投稿では
    DataGridColumn.Widthを設定しています。

    おそらくですが、
    DataGridColumnHeaderとDataGridColumnを同時に設定していませんか?
    その場合、DataGridColumnHeaderが優先されたと思いますが。

    想定した動きにならないのはその辺が原因な気がします。
    今一度、ご自分の書いたソースを点検なさってはいかがでしょうか。

    以上、参考になれば幸いです。
    2011年6月6日 15:57
  • 返信ありがとうございます。

    適切でない書き込みをしてしまいすみません。

    エクスプローラの「列のサイズを自動的に変更する」と「すべての列のサイズを自動的に変更する」を実装しようとしています。(この処理を混同させてしまいました。)

    「列のサイズを自動的に変更する」の処理では、メニュークリックイベントにて右クリックされたカラムヘッダ(header)に対して

    header.Column.Width = DataGridLength.Auto;
    header.Column.Width = header.Column.ActualWidth;
    の処理をしています。

    「すべての列のサイズを自動的に変更する」の処理では、メニュークリックイベントにて

    foreach (DataGridColumn col in dataGrid.Columns)
    {
        col.Width = DataGridLength.Auto;
        col.Width = col.ActualWidth;
    }
    の処理をしています。

    いずれも、この処理の後、対象カラムが「ActualWidth=20」になってしまいます。

    再度、ご教授の程よろしくお願いします。

     

     

    2011年6月7日 6:58
  • DataGridColumnHeaderとDataGridColumnを同時に設定すると、

    どちらか(たぶんDataGridColumnHeader)が優先されて、一方は無視されます。

    >「列のサイズを自動的に変更する」の処理では、メニュークリックイベントにて右クリックされたカラムヘッダ(header)に対して

    これをヘッダでは無くDataGridColumnの幅を設定するように修正してみてはいかがですか。

    2011年6月7日 11:13
  • 処理としては、DataGridColumnのWidthを設定しています。

    header.ColumnはDataGridColumnだと考えているのですが、間違いでしょうか。

    header.Column.Width = DataGridLength.Auto;

    を処理させたメニューイベントの関数内では

    DataGridLength.Autoをセット後には

    header.Column.ActualWidth=20

    header.ActualWidth=「サイズ調整前の幅」

    となっていました。

    再度同じカラムに対してイベントを処理してみると

    DataGridLength.Autoをセットする前に

    header.Column.ActualWidth=「前回のサイズ調整後の幅」

    header.ActualWidth=「前回のサイズ調整後の幅」

    が取得できます。

    Columnのサイズ変更イベントを拾ってそこで処理するのでしょうか。

     

     

    2011年6月8日 6:57
  • すみません、
    DataGridColumnHeader.Widthプロパティと見間違いをしていました。
    ごめんなさい。

    それで、試してみて欲しいのですが
    header.Column.Width = DataGridLength.Auto;
    と、
    header.Column.Width = header.Column.ActualWidth;
    の間に

    dataGrid.UpdateLayout();
    を挟むとどうなりますか?

    # UIElement.UpdateLayout メソッド (System.Windows)
    # http://msdn.microsoft.com/ja-jp/library/system.windows.uielement.updatelayout(v=VS.100).aspx

    • 回答としてマーク たう 2011年6月9日 10:48
    2011年6月8日 9:01
  • Width を変更した後、実際にレイアウトパスが実行される(で、各セルの中身の長さが測定され最終的に列幅が決定され ActualWidth が実際の値を返すようになる)のは少し後のタイミングになりますからね。

    UpdateLayout を呼び出すことでレイアウトパスの実行を強制させることができます。その後 ActualWidth を取得する、というのが一つ。

    逆にレイアウトパスの実行まで待つという観点から、Dispatcher.BeginInvoke で ActualWidth の取得を行うというのが一つ(もちろん、DispatcherPriority.Render よりも低い優先順位で)。

    • 回答としてマーク たう 2011年6月9日 10:48
    2011年6月8日 9:09
  • Tetsuaki Uchida様、Hongliang様

    ご教授ありがとうございます。

    無事解決できました。

    2011年6月9日 10:48