c# – WPF DataBinding当我使用Convert来格式化日期时非常慢
我正在编写一个简单的应用程序来显示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,DateTimeKind.Utc); currentDateTime = currentDateTime.AddSeconds((uint)value); return currentDateTime.ToString(); } 这也很好.但是,事实证明一些原始数据可以是0xFFFFFFFF. public object Convert(object value,System.Globalization.CultureInfo culture) { if ((uint)value == 0xFFFFFFFF) { // don't bother to convert return ((uint)value).ToString("X"); } else { DateTime currentDateTime = new DateTime(2000,DateTimeKind.Utc); currentDateTime = currentDateTime.AddSeconds((uint)value); return currentDateTime.ToString(); } } 它再次起作用,但速度很慢.比原来慢,大约需要10分钟.我很惊讶这一点.这是多少代码运行23,000次的情况吗? 有任何想法吗? 谢谢, 这是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> 解决方法
由于该列是DataGridTextColumn,您可以通过在转换器中返回它来显示0xFFFFFFFF
if ((uint)value == 0xFFFFFFFF) { // don't bother to convert return "0xFFFFFFFF"; } 至于DataGrid很慢,它应该默认使用VirtualizingStackPanel,所以如果你没有改变它,那么它应该非常快,因为你只会使用目前对用户可见的DataGridRows.此外,转换器中的代码几乎没有时间. 因此,你的DataGrid变慢的最可能的原因可能是你已经将ItemsPanel更改为VirtualizingStackPanel以外的其他东西,或者以某种方式禁用了虚拟化,但是如果没有看到你的DataGrid是如何定义的话很难说清楚 编辑 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> 但是使用网格会非常快,因为DataGrid的高度会受到限制,因此可以使用虚拟化 <Grid> <!-- Fast DataGrid with 20000+ items in ItemsSource --> <DataGrid ...> </Grid> (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |