3

(DataContextを使用して)DataViewで埋めるDataGridがあります。別のスレッドでそれを実行しようとしましたが、UIがフリーズします。DataGridにデータを入力するときにUIがフリーズしないようにしたい。

これまでに作成したコードは次のとおりです。

private void btnOK_Click(object sender, RoutedEventArgs e)
    {
        GetFieldsBLL getFieldsBLL = new GetFieldsBLL();
        DataView dv = getFieldsBLL.GetWholeView(ViewName);
        Task task = new Task(() => ucDataExtracViewControl.PopulateGrid(dv));
        task.Start();
    }

public void PopulateGrid(DataView dv)
    {
        dgView.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(delegate{

            dgView.Columns.Clear();
            dgView.AutoGenerateColumns = false;
            foreach (DataColumn column in dv.Table.Columns)
            {
                var gridColumn = new DataGridTextColumn()
                {
                    Header = column.ColumnName,
                    Binding = new Binding("[" + column.ColumnName + "]")
                };

                dgView.Columns.Add(gridColumn);
            }
            dgView.DataContext = dv;

            DataView = dv;
        }));
    }

前もって感謝します!

編集:列を再作成する理由は、一部の列名の名前にドットが含まれているためです。たとえば、「ジョブ番号」。バインディングを使用する場合、データは生成されません。詳細はこちら:ドット付きのDataTable列名がWPFのDataGridコントロールに適さない理由は何ですか?データベースに変更を加えることはできません。– </ p>

4

5 に答える 5

3

私はWPFDataGridでかなり多くの作業を行ってきましたが、レンダリングに問題があります。最終的に、レンダリング時間は、表示する列と行の量になります。DataGridがレンダリングするときは、それぞれを描画する必要があります。つまり、コンテンツのサイズを読み込んで測定します。

固定の列幅と行の高さを設定することで、速度が大幅に向上することがわかりました。以下のDelayedDataGridTextColumnと組み合わせて使用​​すると、各セルが個別にレンダリングされるため、UIスレッドのブロックがほとんどなくなり、UIスレッドで他のことがより高い優先度で発生する可能性があります。

public class DelayedDataGridTextColumn : DataGridTextColumn
{
    protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
    {
        var textBlock = new TextBlock();
        textBlock.SetValue(FrameworkElement.StyleProperty, ElementStyle);

        Dispatcher.BeginInvoke(
            DispatcherPriority.Loaded,
            new Action<TextBlock>(x => x.SetBinding(TextBlock.TextProperty, Binding)),
        textBlock);
        return textBlock;
    }
}

DispatcherPriorityを微調整して、必要なレンダリング速度に合わせることができることに注意してください。優先度が低いほど、カーテン効果が高くなります。優先度が高いほど、レンダリング中に処理される他のアイテムは少なくなります。

于 2012-06-21T08:49:25.227 に答える
1

Change your DispatcherPriority to Background.

dgView.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(delegate{
// your code
};
于 2012-06-21T11:08:49.457 に答える
0

これを実際には別のスレッドで実行することはありません。最初に行うことは、UIスレッドにディスパッチすることです。

問題は、なぜ自分で列を再作成するのかということです。AutoGenerateColumnsこれは、trueに設定するのとは本当に異なる結果をもたらしますか?

WPFのバインディング機能を適切に使用すれば、これを改善できると思いますが、これについて適切な提案を行うためのコードはごくわずかです。

于 2012-06-21T08:37:40.030 に答える
0

BackgroundWorkerクラスを使用して、バックグラウンドプロセスを実行できます。

以下のタスクをDoWorkコールバックに割り当てます

  1. getFieldsBLL.GetWholeView(ViewName);を呼び出します。
  2. 必要な方法でDataViewにデータを入力します

UI更新コード(dgView.DataContext = dv;)をRunWorkerCompletedコールバックに移動します。

注:DoWorkおよびRunWorkerCompletedコールバックに使用できるように、DataViewのクラス変数を作成する必要があります。

于 2012-06-21T14:10:59.550 に答える
0

問題を解決しました。C#コードは、UIがフリーズする理由ではなく、DataGridでのレコードのレンダリングの理由でした。EnableRowVirtualization="True" EnableColumnVirtualization="True" ScrollViewer.CanContentScroll="True"データグリッドに設定

実際、DataGridは大きなデータのUIをフリーズします。したがって、仮想化を有効にすると問題が解決します

于 2021-03-21T06:02:39.383 に答える