I’m writing a simple app to display some data on a DataGrid. The data is just a measurement (float) and a timestamp. The timestamp a uint and is in seconds since 2000.
I sucessfully accomplished the task but did notice it takes a long time (~1 minute) to display the datagrid. There are about 20,000 data. I wouldn’t think 20,000 datum consisting of a uint and a float was that mush. The next request was to display the time as formatted time instead of seconds since 2000. This I did by making the XAML look like this:
<kit:DataGridTextColumn Header="FilteredValue" Binding="{Binding Path=FilteredValue}" />
<kit:DataGridTextColumn Header="Timestamp" Binding="{Binding Path=Timestamp, Converter={StaticResource TimeConverter}}" CanUserSort="False" />
The TimeConverter method looks like:
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();
}
This also worked fine. However, it turns out that some of the raw data can be 0xFFFFFFFF.
This means that there is no data or invalid data. In this case, I don’t want to convert to a date. So I wrote:
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();
}
}
Again, it works, but it’s very slow. Slower than the original and takes about 10 minutes. I was pretty amazed by this. Is it just the case that the extra code is running 23,000 times?
1. What should I be doing? Can I do something in XAML so my Converter is not called if not necessary?
2. When I have 0xFFFFFFFF for one of the measurements (FilteredValues) it gets displayed as NaN. This is probably ok, but it would be nice just to show 0xFFFFFFFF or “no data”. I think it’s getting set to NaN because the underlying data type is a float.
Any ideas?
Thanks,
Dave
Here is the XAML. The last Datagrid is the one of interest. Note that I even set “IsVirtualizing” to True”. Also note the use of ScrollViewer. I did this because otherwise I can’t see all the rows on the last grid (when it finally) displays. Removing this did not speed things up.
<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>
Since the column is a
DataGridTextColumnyou can make it display 0xFFFFFFFF by just returning it in the converterAs for the
DataGridbeing slow, it should be using aVirtualizingStackPanelby default so if you haven’t changed this then it should be pretty fast since you’ll only be working with theDataGridRowsthat are visible to the user at the moment. Also the code in the converter should take virtually no time.So the most likely reason for your
DataGridbeing slow is probably that you’ve changed theItemsPanelto something else than aVirtualizingStackPanelor disabled the virtualization somehow but it’s hard to tell without seeing how yourDataGridis definedEdit
Run the following code after your
DataGridhas finished loading, for example in theLoadedevent for theDataGrid. If theMessageBoxdisplays a large number (shouldn’t be above 50) then you have the source of your problem.For example, using a
StackPanelas the parent panel will be very slow since theDataGridcan consume unlimited vertical space so all the rows will be generatedbut using a
Gridwill be very fast because theDataGridwill be restricted in height so Virtualization can be used