我正在编写一个简单的应用程序来显示DataGrid上的一些数据。数据只是一个度量(浮点数)和一个时间戳。时间戳是一个uint,自2000年以来以秒为单位。
我成功完成了任务,但确实注意到显示数据网格需要很长时间(约1分钟)。大约有20,000个数据。我不认为20,000个由uint和float组成的数据就是那么简单。下一个请求是将时间显示为格式化时间而不是自2000年以来的秒数。这是通过使XAML看起来像这样:
<kit:DataGridTextColumn Header="FilteredValue" Binding="{Binding Path=FilteredValue}" />
<kit:DataGridTextColumn Header="Timestamp" Binding="{Binding Path=Timestamp, Converter={StaticResource TimeConverter}}" CanUserSort="False" />
TimeConverter方法如下所示:
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
DateTime currentDateTime = new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc);
currentDateTime = currentDateTime.AddSeconds((uint)value);
return currentDateTime.ToString();
}
这也很好。但是,事实证明一些原始数据可以是0xFFFFFFFF。 这意味着没有数据或无效数据。在这种情况下,我不想转换为日期。所以我写道:
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if ((uint)value == 0xFFFFFFFF)
{
// don't bother to convert
return ((uint)value).ToString("X");
}
else
{
DateTime currentDateTime = new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc);
currentDateTime = currentDateTime.AddSeconds((uint)value);
return currentDateTime.ToString();
}
}
同样,它有效,但它非常慢。比原来慢,大约需要10分钟。我很惊讶这一点。这是多少代码运行23,000次的情况吗? 1.我该怎么办?我可以在XAML中执行某些操作,以便在没有必要时调用我的Converter吗? 2.当我有一个测量值(FilteredValues)的0xFFFFFFFF时,它显示为NaN。这可能没问题,但只显示0xFFFFFFFF或“无数据”会很好。我认为它已经设置为NaN,因为底层数据类型是浮点数。
有什么想法吗?
谢谢, 戴夫
这是XAML。最后一个Datagrid是感兴趣的。请注意,我甚至将“IsVirtualizing”设置为True。还要注意使用ScrollViewer。我这样做是因为否则我无法看到最后一个网格上的所有行(最终显示)。删除它并没有加快速度。
<Window x:Class="STDatabaseReader.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:chartingToolkit="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit" xmlns:kit="http://schemas.microsoft.com/wpf/2008/toolkit" xmlns:local="clr-namespace:STDatabaseReader"
Title="Smart Transmitter Database Reader">
<Window.Resources>
<local:BytesToStringConverter x:Key="BytesToStringConverter"></local:BytesToStringConverter>
<local:TimeConverter x:Key="TimeConverter"></local:TimeConverter>
</Window.Resources>
<Grid>
<ScrollViewer>
<StackPanel Orientation="Vertical">
<Button Name="m_btnFetchData" HorizontalAlignment="Left" Click="m_btnFetchData_Click">Fetch File</Button>
<StackPanel Orientation="Horizontal">
<StackPanel Orientation="Vertical">
<Label HorizontalAlignment="Center">Partition 1</Label>
<kit:DataGrid Name="m_gridPartion1" AutoGenerateColumns="False">
<kit:DataGrid.Columns>
<kit:DataGridTextColumn Header="Header Info" Binding="{Binding Path=HeaderInfo, Converter={StaticResource BytesToStringConverter}}" CanUserSort="False" />
<kit:DataGridTextColumn Header="Transmitter Id" Binding="{Binding Path=TransmitterId, Converter={StaticResource BytesToStringConverter}}" CanUserSort="False" />
<kit:DataGridTextColumn Header="DeviceNumber" Binding="{Binding Path=DeviceNumber}" />
<kit:DataGridTextColumn Header="HardwareVersion" Binding="{Binding Path=HardwareVersion}" />
<kit:DataGridTextColumn Header="CRC" Binding="{Binding Path=CRC}" />
</kit:DataGrid.Columns>
</kit:DataGrid>
</StackPanel>
<StackPanel Orientation="Vertical">
<Label HorizontalAlignment="Center">Partition 3</Label>
<kit:DataGrid Name="m_gridPartion3" AutoGenerateColumns="False">
<kit:DataGrid.Columns>
<kit:DataGridTextColumn Header="Header Info" Binding="{Binding Path=HeaderInfo, Converter={StaticResource BytesToStringConverter}}" CanUserSort="False" />
<kit:DataGridTextColumn Header="SystemTime" Binding="{Binding Path=SystemTime, Converter={StaticResource TimeConverter}}" />
</kit:DataGrid.Columns>
</kit:DataGrid>
</StackPanel>
</StackPanel>
<StackPanel Orientation="Vertical">
<Label HorizontalAlignment="Center">Partition 2</Label>
<kit:DataGrid Name="m_gridPartion2" AutoGenerateColumns="False">
<kit:DataGrid.Columns>
<kit:DataGridTextColumn Header="Header Info" Binding="{Binding Path=HeaderInfo, Converter={StaticResource BytesToStringConverter}}" CanUserSort="False" />
<kit:DataGridTextColumn Header="FirmwareRevision" Binding="{Binding Path=FirmwareRevision, Converter={StaticResource BytesToStringConverter}}" CanUserSort="False" />
<kit:DataGridTextColumn Header="SoftwarePartNumber" Binding="{Binding Path=SoftwarePartNumber, Converter={StaticResource BytesToStringConverter}}" CanUserSort="False" />
<kit:DataGridTextColumn Header="FirmwareUpgradeTime" Binding="{Binding Path=FirmwareUpgradeTime,Converter={StaticResource TimeConverter}}" />
<kit:DataGridTextColumn Header="DatabaseEraseTime" Binding="{Binding Path=DatabaseEraseTime,Converter={StaticResource TimeConverter}}" />
<kit:DataGridTextColumn Header="RangeEnzymeElectrode" Binding="{Binding Path=RangeEnzymeElectrode}" />
<kit:DataGridTextColumn Header="OffsetEnzymeElectrode" Binding="{Binding Path=OffsetEnzymeElectrode}" />
<kit:DataGridTextColumn Header="BiasValue" Binding="{Binding Path=BiasValue}" />
</kit:DataGrid.Columns>
</kit:DataGrid>
</StackPanel>
<StackPanel Orientation="Horizontal">
<StackPanel Orientation="Vertical">
<Label HorizontalAlignment="Center">Partition 4 - HeaderInfo</Label>
<kit:DataGrid Name="m_gridDataHeader" AutoGenerateColumns="False">
<kit:DataGrid.Columns>
<kit:DataGridTextColumn Header="Header Info" Binding="{Binding Path=HeaderInfo, Converter={StaticResource BytesToStringConverter}}" CanUserSort="False" />
</kit:DataGrid.Columns>
</kit:DataGrid>
</StackPanel>
<StackPanel Orientation="Vertical">
<Label HorizontalAlignment="Center">Partition 4 - Chemistry Data</Label>
<kit:DataGrid Name="m_gridData" AutoGenerateColumns="False" VirtualizingStackPanel.IsVirtualizing="True" Loaded="m_gridData_Loaded">
<kit:DataGrid.Columns>
<!--
<kit:DataGridTextColumn Header="Noise" Binding="{Binding Path=Noise, StringFormat=\{0:X8\}}" />
<kit:DataGridTextColumn Header="FilteredValue" Binding="{Binding Path=FilteredValue, StringFormat='X'}" />
<kit:DataGridTextColumn Header="Timestamp" Binding="{Binding Path=Timestamp, StringFormat=\{0:X\}}" /> -->
<kit:DataGridTextColumn Header="Noise" Binding="{Binding Path=Noise}" />
<kit:DataGridTextColumn Header="FilteredValue" Binding="{Binding Path=FilteredValue}" />
<kit:DataGridTextColumn Header="Timestamp" Binding="{Binding Path=Timestamp, Converter={StaticResource TimeConverter}}" CanUserSort="False" />
</kit:DataGrid.Columns>
</kit:DataGrid>
</StackPanel >
</StackPanel>
</StackPanel>
</ScrollViewer>
</Grid>
答案 0 :(得分:2)
由于该列是DataGridTextColumn
,您可以通过在转换器中返回它来显示0xFFFFFFFF
if ((uint)value == 0xFFFFFFFF)
{
// don't bother to convert
return "0xFFFFFFFF";
}
至于DataGrid
速度很慢,默认情况下应该使用VirtualizingStackPanel
,所以如果你没有改变它,那么它应该非常快,因为你只会使用{目前用户可以看到{1}}。此外,转换器中的代码几乎没有时间。
因此,DataGridRows
速度缓慢的最可能原因可能是您已将DataGrid
更改为除ItemsPanel
以外的其他内容或以某种方式禁用虚拟化,但很难说没有看到VirtualizingStackPanel
的定义方式
修改强>
DataGrid
完成加载后运行以下代码,例如DataGrid
的{{1}}事件。如果Loaded
显示大量(不应超过50),那么您就有问题的根源。
DataGrid
例如,使用MessageBox
作为父面板会非常慢,因为private void DataGrid_Loaded(object sender, RoutedEventArgs e)
{
DataGrid dataGrid = sender as DataGrid;
List<DataGridRow> generatedDataGridRows = VisualTreeHelpers.GetVisualChildCollection<DataGridRow>(dataGrid);
MessageBox.Show(generatedDataGridRows.Count.ToString());
}
public static List<T> GetVisualChildCollection<T>(object parent) where T : Visual
{
List<T> visualCollection = new List<T>();
GetVisualChildCollection(parent as DependencyObject, visualCollection);
return visualCollection;
}
private static void GetVisualChildCollection<T>(DependencyObject parent, List<T> visualCollection) where T : Visual
{
int count = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < count; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(parent, i);
if (child is T)
{
visualCollection.Add(child as T);
}
else if (child != null)
{
GetVisualChildCollection(child, visualCollection);
}
}
}
会消耗无限的垂直空间,因此会生成所有行
StackPanel
但使用DataGrid
会非常快,因为<StackPanel>
<!-- Slow DataGrid with 20000+ items in ItemsSource -->
<DataGrid ...>
</StackPanel>
的高度会受到限制,因此可以使用虚拟化
Grid