4

データベースからlinq-to-sqlによって入力されたリストにバインドされたWPFデータグリッドがあります。バインディングは双方向であり、ユーザーは各行の値を変更できます

        <wpf:DataGrid AutoGenerateColumns="False" 
              ItemsSource="{Binding MyList}" 
              SelectedItem="{Binding SelectedItem}" >

約 20000 行を表示すると、リストの初期化中にメモリ不足の例外でプログラムがクラッシュします。行数が少なくても、パフォーマンスが耐えられないほど遅くなります。

初期化時に、データグリッドが各行を反復処理して、最大列幅とその他のプロパティを測定することを知っています。画面上にあるかどうかに関係なく、すべての行に対して明らかにそうします。

myQuery.ToList()データグリッドをバインドする(列をクリックしてデータグリッドをソートできるようにする) か、IQueryable に直接バインドしようとしました。(並べ替えはそれでは機能しません)

どちらも同じ結果になります。20000 個の項目を持つ ToList() だけでは、大量のメモリが消費されることはありません。これは、 datagrid にバインドされている場合にのみ発生します。

データグリッド内の 20000 行がどれほど有用であるかという問題を無視します (これらは現在の要件です。これらを変更するには、実際の例が役立ちます)。

現在画面に表示されているデータのみを遅延ロードし、スクロールして表示されるまで他のすべてを無視する最も簡単な方法は何ですか?

これは、サードパーティのライブラリや主要なコード変更なしで実行できますか?

そうでない場合、推奨される回避策は何ですか?

4

2 に答える 2

5

問題は完全に私の側のユーザーエラーであることが判明しました:

WPF Datagrid は UI の仮想化を問題なく実行できます。メモリを消費する行オブジェクトは、必要な場合にのみ描画されます。行がデータグリッドの可視範囲外にある場合、インスタンス化されません。

ただし、データグリッドが ScrollViewer 内に含まれている場合、これは機能しません。scrollviewer 内では、データグリッドのすべての部分が仮想的に表示されるため、データグリッド全体がレンダリングされます。スクロールビューアは、このレンダリングされたデータグリッドの UI ウィンドウ内に収まる部分のみを表示します。

scrollviewer 内の datagrid は、独自のスクロールバーを管理する datagrid のように見えるため、scrollviewer に気付きませんでした。

scrollviewer を削除すると、高さと幅が可変であっても、大量の行がまったく問題になりません。データグリッドは単に利用可能なスペースを埋め、必要に応じて新しい行のみをインスタンス化します。

つまり、私の問題の解決策は次のとおりです。スクロールビューアー内にデータグリッドを配置しないでください

于 2012-06-05T16:27:11.953 に答える
0

このケースでバインドしているプロパティはMyList、MyFile オブジェクト ( List<MyFile>) で構成されているとしましょう。次に、MyFile クラスを次のように作成する必要があります。

 class MyFile
    {
        public string FullPath { get; set; }

        public string Extension
        {
            get
            {
                return Path.GetExtension(FullPath);
            }
        }

        public string PathRoot
        {
            get
            {
                return Path.GetPathRoot(FullPath);
            }
        }

        public DateTime CreationTime
        {
            get
            {
                return File.GetCreationTime(FullPath);
            }
        }

    }

そうすれば、各オブジェクトに保存する情報が少なくなり、グリッドに表示されるいくつかのアイテムで get メソッドを呼び出すことができます。クラスに実際の値を格納することとは対照的です。お役に立てれば

于 2012-05-03T01:31:14.247 に答える