【发布时间】:2011-10-28 07:55:24
【问题描述】:
我正在开发一个简单的 WPF 应用程序,它执行 SQL 查询并在 DataGrid 中显示结果数据。
一切都按预期工作,只是性能很糟糕。从单击按钮加载数据到实际看到数据显示在 DataGrid 中的时间长度约为 3-4 秒。打开行虚拟化会快一点,但我不得不将其关闭,因为我需要能够对滚动后不再可见的单元格执行操作。即使启用了虚拟化,显示数据的速度也比我想的要慢。
我最初认为是 SQL 数据库运行缓慢,但我做了一些测试,发现我正在将 SQL 服务器中的所有数据(数百行)在几分之一秒内读取到 DataTable 中。直到我将 DataTable 绑定到 DataGrid 的 DataContext 之后,所有内容才会锁定几秒钟。
那么为什么 DataContext 这么慢呢?我的电脑是全新的,所以考虑到我一开始检索数据的速度,我很难理解为什么填写 DataGrid 需要这么长的时间。
(我也尝试绑定到 DataGrid 的 ItemSource 而不是 DataContext,但性能是一样的。)
是否有另一种方法可以将数据加载到性能更合理的 DataGrid 中?如果需要,即使是 DataGrid 的替代品也值得探索。
编辑:在 Vlad 的建议下,我尝试了另一个绕过 SQL 查询的测试。我改为用 1000 行随机生成的数据填充 DataTable。不用找了。数据在一秒钟内生成并写入 DataTable。但是,将其附加到 DataGrid 需要 20 多秒。
下面是我正在使用的 DataGrid XAML。除了绑定之外,非常简单,没有附加任何自定义代码。
<DataGrid ItemsSource="{Binding}" AutoGenerateColumns="False" Name="dataGridWellReadings" GridLinesVisibility="None" CanUserResizeRows="False" SelectionUnit="Cell" AlternatingRowBackground="#FFE0E0E0" RowBackground="#FFF0F0F0" HorizontalScrollBarVisibility="Disabled" SelectedCellsChanged="dataGridWellReadings_SelectedCellsChanged" EnableRowVirtualization="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Date" Binding="{Binding readingDate, StringFormat=yyyy-MM-dd}" Width="3*">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="KeyboardNavigation.IsTabStop" Value="False" />
<Setter Property="BorderThickness" Value="0"/>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="Pt" Binding="{Binding readingPt, StringFormat=0.#}" Width="2*">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="KeyboardNavigation.IsTabStop" Value="False" />
<Setter Property="BorderThickness" Value="0"/>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="Pc" Binding="{Binding readingPc, StringFormat=0.#}" Width="2*">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="KeyboardNavigation.IsTabStop" Value="False" />
<Setter Property="BorderThickness" Value="0"/>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="Ppl" Binding="{Binding readingPpl, StringFormat=0.#}" Width="2*">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="KeyboardNavigation.IsTabStop" Value="False" />
<Setter Property="BorderThickness" Value="0"/>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="MCFD" Binding="{Binding readingMCFD, StringFormat=0.#}" Width="2*">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="KeyboardNavigation.IsTabStop" Value="False" />
<Setter Property="BorderThickness" Value="0"/>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="Water Produced" Binding="{Binding readingWaterProduced, StringFormat=0.#}" Width="3*">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="KeyboardNavigation.IsTabStop" Value="False" />
<Setter Property="BorderThickness" Value="0"/>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="Water Hauled" Binding="{Binding readingWaterHauled, StringFormat=0.#}" Width="3*">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="KeyboardNavigation.IsTabStop" Value="False" />
<Setter Property="BorderThickness" Value="0"/>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="Temperature" Binding="{Binding readingTemperature, StringFormat=0.#}" Width="3*">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="KeyboardNavigation.IsTabStop" Value="False" />
<Setter Property="BorderThickness" Value="0"/>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="Hours On (actual)" Binding="{Binding readingHoursOnActual, StringFormat=0.#}" Width="3*">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="KeyboardNavigation.IsTabStop" Value="False" />
<Setter Property="BorderThickness" Value="0"/>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="Hours On (planned)" Binding="{Binding readingHoursOnPlanned, StringFormat=0.#}" Width="3*">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="KeyboardNavigation.IsTabStop" Value="False" />
<Setter Property="BorderThickness" Value="0"/>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="Clock Cycles" Binding="{Binding readingClockCycles, StringFormat=0.#}" Width="3*">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="KeyboardNavigation.IsTabStop" Value="False" />
<Setter Property="BorderThickness" Value="0"/>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
【问题讨论】:
-
你确定是DataContext慢吗?可能是 LINQ 没有具体化查询,而是在 UI 绑定到它时懒惰地执行它。检查您是否在非 UI 线程中实现查询。
-
... 或者只是在没有数据库访问权限的情况下尝试相同的代码,只是使用一些假数据。
-
好的,我没有使用数据库再次测试,只是使用了1000行随机生成的数据。同样,数据在一秒钟内生成并写入 DataTable。但是,将其附加到 DataGrid 需要 20 多秒。
标签: c# wpf performance wpfdatagrid