WPF应用程序DataGrid控件窗口在非虚拟化DataGrid中的许多行时切换滞后

Gau*_*rma 9 .net c# wpf datagrid wpfdatagrid

我们有一个小的.NET 4.0 DataGrid WPF演示,其代码如下所示.它由一个包含30列和3000行的非虚拟化DataGrid组成.由于我们需要不支持虚拟化的分组功能,因此它是非虚拟化的.

当您运行此应用程序,并在它和其他窗口之间切换时,有一个明显的滞后(约1秒).这仅在重新激活窗口时发生 - 一旦激活,在内部单击没有相关的延迟.

我们已经使用性能分析器对窗口重新激活时发生的这种滞后进行了分析,并发现当窗口重新聚焦时会触发很多依赖属性通知.我们不知道为什么会这样,而且似乎没必要.

我们发现此延迟与DataGrid中的行数成比例.有谁知道我们如何消除或减少这种滞后?

更新:似乎即使停留在应用程序内部,但专注于另一个控件(如网格外的文本框),也会出现焦点延迟.因此,我们现在知道它不是一个窗口切换问题,而是一个由焦点变化引起的问题,但仍然不确定其确切原因.

(MainWindow.xaml)

<Window x:Class="WpfApplication20.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">
    <Grid>
        <DataGrid Name="dataGrid" VirtualizingStackPanel.IsVirtualizing="False" AutoGenerateColumns="True"/>
    </Grid>
</Window>
Run Code Online (Sandbox Code Playgroud)

(MainWindow.xaml.cs)

using System.Collections.Generic;
using System.Windows;

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

            List<Row> rows = new List<Row>();

            for(int i = 0; i < 3000; i++)
            {
                Row row = new Row(i);
                rows.Add(row);
            }

            dataGrid.ItemsSource = rows;
        }
    }

    public class Row
    {
        public double Double1 { get; set; }
        public double Double2 { get; set; }
        public double Double3 { get; set; }
        public double Double4 { get; set; }
        public double Double5 { get; set; }
        public double Double6 { get; set; }
        public double Double7 { get; set; }
        public double Double8 { get; set; }
        public double Double9 { get; set; }
        public double Double10 { get; set; }
        public double Double11 { get; set; }
        public double Double12 { get; set; }
        public double Double13 { get; set; }
        public double Double14 { get; set; }
        public double Double15 { get; set; }
        public double Double16 { get; set; }
        public double Double17{ get; set; }
        public double Double18 { get; set; }
        public double Double19 { get; set; }
        public double Double20 { get; set; }
        public double Double21 { get; set; }
        public double Double22 { get; set; }
        public double Double23 { get; set; }
        public double Double24 { get; set; }
        public double Double25 { get; set; }
        public double Double26 { get; set; }
        public double Double27 { get; set; }
        public double Double28 { get; set; }
        public double Double29 { get; set; }
        public double Double30 { get; set; }

        public Row(double d)
        {
            Double1 = d;
            Double2 = d + 1;
            Double3 = d + 2;
            Double4  = d + 3;
            Double5  = d + 4;
            Double6  = d + 5;
            Double7  = d + 6;
            Double8  = d + 7;
            Double9  = d + 8;
            Double10 = d + 9;
            Double11 = d + 10;
            Double12 = d + 11;
            Double13 = d + 12;
            Double14 = d + 13;
            Double15 = d + 14;
            Double16 = d + 15;
            Double17 = d + 16;
            Double18 = d + 17;
            Double19 = d + 18;
            Double20 = d + 19;
            Double21 = d + 20;
            Double22 = d + 21;
            Double23 = d + 22;
            Double24 = d + 23;
            Double25 = d + 24;
            Double26 = d + 25;
            Double27 = d + 26;
            Double28 = d + 27;
            Double29 = d + 28;
            Double30 = d + 29;
        }             
    }                 
}
Run Code Online (Sandbox Code Playgroud)

(组样式 - 可选择通过放入DataGrid XML来实现):

<!--<DataGrid.GroupStyle>
                <GroupStyle>
                    <GroupStyle.ContainerStyle>
                        <Style TargetType="{x:Type GroupItem}">
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="{x:Type GroupItem}">
                                        <Border BorderBrush="DarkGray" BorderThickness="1" Padding="4,0" >
                                            <Expander VerticalContentAlignment="Center" IsExpanded="True">
                                                <Expander.Header>
                                                    <Canvas>
                                                        <StackPanel Orientation="Horizontal" Canvas.Top="-11" Canvas.Left="4">
                                                            <Label Content="{Binding Name}" Visibility="{Binding DataContext.ShowGroupHeaderVisibility, RelativeSource={RelativeSource AncestorType=DataGrid}}"/>
                                                            <Label Content="{Binding ItemCount}" Visibility="{Binding DataContext.ShowGroupCountVisibility, RelativeSource={RelativeSource AncestorType=DataGrid}}"/>
                                                        </StackPanel>
                                                    </Canvas>
                                                </Expander.Header>
                                                <ItemsPresenter/>
                                            </Expander>
                                        </Border>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </GroupStyle.ContainerStyle>
                </GroupStyle>
            </DataGrid.GroupStyle>-->
Run Code Online (Sandbox Code Playgroud)

Gau*_*rma 1

对于那些感兴趣的人,我们通过在应用程序中定义单独的焦点范围来解决这个问题。默认情况下,整个窗口都是焦点范围。创建单独的窗口并确保在窗口停用和再次激活之前将焦点范围设置为网格以外的其他内容,以确保窗口快速移动和返回。我们假设 WPF 中有一些未记录的功能会产生这种现象。