Here's a simple WPF program (most of the code is in the code-behind):
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;
}
}
}
}
You'll need the System.Management.Automation.dll nuget package to build this test program.
Here's what it looks like when run:
Note that the DataGrid ItemsSource is set to the result of a PowerShell command.
In that case, we're only displaying 20 Process objects in the DataGrid.
With only 20 items, the program opens quickly and is responsive.
If we change this line:
var result = ps.AddScript("get-process | select-object -first 20").Invoke();
to the following:
var result = ps.AddScript("get-process").Invoke();
the program becomes non-responsive. Note that on my system, there are over 370 processes in the list; results may vary on your system.
How can the program be made to be responsive in the case of a large amount of items?
Please note that the particular arrangement of the WPF items:
DockPanel -> ScrollViewer -> TextBlock -> Inline -> DataGrid
is meant to simulate another program that this one is meant to demonstrate the issue in. So that's why it's setup in this way.
If there aren't enough processes running on your system to experience the slow down, you can also use something like the following:
var result = ps.AddScript("get-process | select-object -first 20; get-process | select-object -first 20; get-process | select-object -first 20").Invoke();
To simulate a larger number of processes. (Consider getting the count to over 300.)

Setting the
MaxHeightof theDataGridsolved the issue:It's blazing fast now!
One theory is that, without a
MaxHeight, the wholeDataGridis shown, thus turning off virtualization.MaxHeightcauses aScrollViewerto engage after a certain height is surpassed, which seems to allow for virtualization.