当源大小较大时,带有PowerShell中项目的DataGrid非常慢

时间:2019-05-16 02:55:38

标签: c# wpf powershell wpfdatagrid

这是一个简单的WPF程序(大多数代码在后面的代码中):

MainWindow.xaml

<Window x:Class="WpfTextBlockInlineDataGridPSProcessSource.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfTextBlockInlineDataGridPSProcessSource"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>

    </Grid>
</Window>

MainWindow.xaml.cs

using System.Diagnostics;
using System.Linq;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;

using static System.Console;

namespace WpfTextBlockInlineDataGridPSProcessSource
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();


            var runspace = RunspaceFactory.CreateRunspace(InitialSessionState.CreateDefault());

            runspace.Open();

            var ps = PowerShell.Create();

            ps.Runspace = runspace;

            // var result = ps.AddScript("get-process").Invoke();

            var result = ps.AddScript("get-process | select-object -first 20").Invoke();


            WriteLine(result.Count);


            if (result.All(elt => elt.BaseObject is Process))
            {

                var data_grid = new DataGrid()
                {
                    ItemsSource = result,

                    IsReadOnly = true,

                    AutoGenerateColumns = false
                };

                data_grid.Columns.Add(new DataGridTextColumn()
                {
                    Header = "ProcessName",
                    Binding = new Binding("ProcessName"),
                });

                var text_block = new TextBlock();

                var scroll_viewer = new ScrollViewer();

                scroll_viewer.Content = text_block;

                text_block.Inlines.Add(data_grid);

                text_block.Inlines.Add(new LineBreak());

                var dock_panel = new DockPanel();

                dock_panel.Children.Add(scroll_viewer);

                Content = dock_panel;
            }
        }
    }
}

您将需要System.Management.Automation.dll nuget软件包来构建此测试程序。

这是运行时的样子:

enter image description here

请注意,DataGrid ItemsSource设置为PowerShell命令的结果。

在这种情况下,我们仅在Process中显示20个DataGrid对象。

只有20个项目,该程序会快速打开并响应。

如果我们更改此行:

var result = ps.AddScript("get-process | select-object -first 20").Invoke();

到以下:

var result = ps.AddScript("get-process").Invoke();

程序变得无响应。请注意,在我的系统上,列表中有370多个进程。结果可能会因您的系统而异。

如果有大量物品,如何使程序具有响应能力?

请注意WPF项目的特殊安排:

DockPanel-> ScrollViewer-> TextBlock-> Inline-> DataGrid

旨在模拟另一个旨在演示该问题的程序。这就是为什么以这种方式进行设置。

如果系统上没有足够的进程运行以降低速度,则还可以使用以下内容:

var result = ps.AddScript("get-process | select-object -first 20; get-process | select-object -first 20; get-process | select-object -first 20").Invoke();

模拟大量进程。 (请考虑使计数超过300。)

1 个答案:

答案 0 :(得分:0)

设置MaxHeight中的DataGrid解决了该问题:

var data_grid = new DataGrid()
{
    ItemsSource = result,

    IsReadOnly = true,

    MaxHeight = 800,

    AutoGenerateColumns = false
};

现在正在快速燃烧!

一种理论是,如果没有MaxHeight,将显示整个DataGrid,从而关闭虚拟化。 MaxHeight导致ScrollViewer超过一定高度后进入,这似乎可以进行虚拟化。