none
DataGrid.EnableColumnVirtualization=trueに設定した場合の挙動 RRS feed

  • 質問

  • DataGridを利用したアプリケーションを作成していますが、EnableColumnVirtualizationプロパティとEnableRowVirtualizationプロパティを利用していたところ問題が発生したので質問させてください。

    ソースを以下の通りです。

    ■XAML
    <Window x:Class="Art55.DataGridDemo20150122_001.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Window.Resources>
            <Style TargetType="{x:Type DataGrid}">
                <Setter Property="EnableColumnVirtualization" Value="True" />
                <Setter Property="EnableRowVirtualization" Value="True" />
            </Style>
        </Window.Resources>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="300" />
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
            <DataGrid x:Name="DataGrid1" Grid.Column="1" />
            <DataGrid x:Name="DataGrid2" Grid.Column="2" />
        </Grid>
    </Window>

    ■コードビハインド
    namespace Art55.DataGridDemo20150122_001
    {
        public partial class MainWindow
        {
            public MainWindow()
            {
                InitializeComponent();

                DataGrid1.ItemsSource = Enumerable
                    .Range(1, 100)
                    .Select(n => new {Column1 = "A" + n, Column2 = "B" + n, Column3 = "C" + n,})
                    .ToList();

                DataGrid2.ItemsSource = Enumerable
                    .Range(1, 100)
                    .Select(n => new { Column1 = "A" + n, Column2 = "B" + n, Column3 = "C" + n, })
                    .ToList();
            }
        }
    }

    このアプリケーションを実行したところ、マウスにてウインドウのサイズを小さくしていくと、ときどきDataGridの縦スクロールバーが出たり消えたりするようになり、マウス自体は動くのですが、アプリケーションはおろか他のアプリケーションも操作不能になります。おそらく原因はEnableColumnVirtualizationとEnableRowVirtualizationがTureになっていることで、DataGrid中のカラムが見えないサイズになったタイミングで内部のコンテンツがなくなり、スクロールバーが消え、スクロールバーが消えたことにより、内部のコンテンツが描画できるようになり、またスクロールバーが表示されるとうことを繰り返しているのだと思うのですが、操作不能になるのは非常に不味いため、何かの対応をご助言いただきたいと考えています。

    ※DataGrid.MinWidthを30px程度に指定すると、現象が再現しなくなりましたが、他の方法もないものかと・・・。

    2015年1月22日 5:16

回答

  • 再現しました。
    RowHeader列が表示されたり消えたり繰り返してます。

    どうやら、ScrollViewerのScrollBarより内側の表示領域の幅が、RowHeaderの幅を下回る(未満?以下?)と発生するようです。
    RowHeaderWidthを例えば100などに設定しておいて、RowHeaderより狭くしていくと行の高さも急に小さくなるので、このタイミングで発生だと思われます。
    MinWidthを30にした場合に発症しないのはRowHeader列の幅を下回っていないからではないでしょうか。

    発症するとDataGrid.CellsPanelHorizontalOffsetやRowHeaderActualWidthが大きな値と正常な値を繰り返しているようで、レイアウト計算が終わらなくなります。
    art55さんが推測しているように、列が仮想化されているのでこのような変な挙動になるのでしょう。

    で、いろいろ試してみたところDataGrid.RowHeaderWidthに適当な値を設定しておくと回避できるようです。
    RowHeaderWidthが設定されることでRowHeader列が消えなくなるのでしょう。


    あと、なぜかよくわからないですが、DataGridを継承だけして何も変更していないDataGridを使うと発症しません。
    テンプレート適用の順番でも影響しているのだろうか・・・謎です。

    訂正:
    スタイルが適用されてなかっただけでした。


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 編集済み gekkaMVP 2015年1月23日 0:38
    • 回答としてマーク art55 2015年1月23日 2:34
    2015年1月22日 12:02

すべての返信

  • このアプリケーションを実行したところ、マウスにてウインドウのサイズを小さくしていくと、ときどきDataGridの縦スクロールバーが出たり消えたりするようになり、マウス自体は動くのですが、アプリケーションはおろか他のアプリケーションも操作不能になります。

    以下の現象ですね。動画キャプチャ撮ってみました。

    https://www.youtube.com/watch?v=mTEO1CcFFVk

    当方の環境 「Corei7-2600、GrForce GT530(最新ドライバー更新済)、Windows7 SP1、Visual Studio 2013 Update4」  にて、.NET Framework 4.5 でプロジェクトを作成し試してみたら現象がこちらでも再現しました。原因は不明ですが DataGrid の不具合の可能性が高いように思えます。Connect へフィードバックを送信した方がいいかも知れません(すでに挙がってる可能性もあります)

    個人的には、標準 DataGrid の性能に関して懐疑的なため、ベンダー製の DataGrid を使用するか、ListView 等の Items コントロールを DataTemplate でカスタマイズして使用してます。単純なリスト表示であれば ListView で充分だと思ってます。


    「不適切な発言」の濫用はフォーラムの運営を妨げる行為です。ご遠慮ください https://social.msdn.microsoft.com/Forums/ja-JP/0f7b0966-0141-4c1b-b7b9-aed65abf60b6?forum=announceja


    2015年1月22日 7:04
    モデレータ
  • VS2013で再現しました。現象としては、art55さんが書かれている理由によるのだと私も思います。そこで、以下のようにスクロールバーを常に表示するようにしたところ、問題が発生しなくなったようです。スクロールバーを常に表示と言っても、スクロールボックス(マウスでクリックして上下や左右に動かすところ)はウインドウのサイズを小さくしていくと消えますから、さほど違和感を感じません。

    <Style TargetType="{x:Type DataGrid}">
        <Setter Property="EnableColumnVirtualization" Value="True" />
        <Setter Property="EnableRowVirtualization" Value="True" />
        <Setter Property="HorizontalScrollBarVisibility" Value="Visible" />
        <Setter Property="VerticalScrollBarVisibility" Value="Visible" />
    </Style>

    いずれにしても通常のコーディングで不具合が発生しますので、フィードバックした方が良さそうですね。フィードバックは、「Microsoft Visual Studio 2013 フィードバック ツール」が使えます。
    #VS2012版もあります。

    #追記

    すみません。ウソ言いました。上記のコードでも問題の現象が発生してしまいました・・・orz


    ★良い回答には回答済みマークを付けよう! MVP - .NET  http://d.hatena.ne.jp/trapemiya/


    2015年1月22日 7:07
    モデレータ
  • 再現しました。
    RowHeader列が表示されたり消えたり繰り返してます。

    どうやら、ScrollViewerのScrollBarより内側の表示領域の幅が、RowHeaderの幅を下回る(未満?以下?)と発生するようです。
    RowHeaderWidthを例えば100などに設定しておいて、RowHeaderより狭くしていくと行の高さも急に小さくなるので、このタイミングで発生だと思われます。
    MinWidthを30にした場合に発症しないのはRowHeader列の幅を下回っていないからではないでしょうか。

    発症するとDataGrid.CellsPanelHorizontalOffsetやRowHeaderActualWidthが大きな値と正常な値を繰り返しているようで、レイアウト計算が終わらなくなります。
    art55さんが推測しているように、列が仮想化されているのでこのような変な挙動になるのでしょう。

    で、いろいろ試してみたところDataGrid.RowHeaderWidthに適当な値を設定しておくと回避できるようです。
    RowHeaderWidthが設定されることでRowHeader列が消えなくなるのでしょう。


    あと、なぜかよくわからないですが、DataGridを継承だけして何も変更していないDataGridを使うと発症しません。
    テンプレート適用の順番でも影響しているのだろうか・・・謎です。

    訂正:
    スタイルが適用されてなかっただけでした。


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 編集済み gekkaMVP 2015年1月23日 0:38
    • 回答としてマーク art55 2015年1月23日 2:34
    2015年1月22日 12:02
  • ひらぽん様

    わざわざ動画を撮っていただきありがとうございます。
    私の稚拙な説明で現象が伝わるか不安だったので大変助かりました。

    > DataGrid の不具合の可能性が高いように思えます。

    ここのパーツの動きは正しいような気もしますが、DataGrid全体でみると、私も不具合ではないかと思っていたりします。
    対応方法が落ち着き次第、Connect へフィードバックも検討したいと思います。

    DataGridを継承し、編集後の次のセルへの遷移、独自に用意したデータ用のカスタマイズ等が
    行われている状態でこの現象を発見してしまったので、別コントロールへ換えるのは厳しい状況です。
    別の機会があれば検討させていただきます。

    2015年1月23日 2:09
  • trapemiya 様

    Microsoft Visual Studio 2013 フィードバック ツールのご紹介ありがとうございました。

    また、スクロールバーをつねに表示させれば、現象は発生しないと
    私も考えておりましたが、実際は違ったようですね。
    私の質問の内容だけでは、そのように誤解されてしまう方がいらっしゃると思うので
    間違いが明確になり有益な情報になったと思います。
    ありがとうございました。

    2015年1月23日 2:13
  • gekka様

    RowHeaderWidthに固定値を設定しておくと、現象が発生しないことが、こちらでも確認できました。
    固定値を設定することで悪影響がないことが確認できれば、この方法を採用したいと思います。
    大変有益な情報をありがとうございました。

    2015年1月23日 2:34