Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当我使用Convert格式化日期时,WPF数据绑定非常慢_C#_Wpf_Datagrid_Converter_Ivalueconverter - Fatal编程技术网

C# 当我使用Convert格式化日期时,WPF数据绑定非常慢

C# 当我使用Convert格式化日期时,WPF数据绑定非常慢,c#,wpf,datagrid,converter,ivalueconverter,C#,Wpf,Datagrid,Converter,Ivalueconverter,我正在编写一个简单的应用程序,在DataGrid上显示一些数据。数据只是一个测量值(浮点)和一个时间戳。自2000年以来,时间戳以秒为单位 我成功地完成了任务,但注意到显示数据网格需要很长时间(约1分钟)。大约有20000个数据。我不认为20000个数据由一个uint和一个浮动组成是那么糟糕。下一个请求是将时间显示为格式化时间,而不是自2000年以来的秒数。我这样做是通过使XAML看起来像这样: <kit:DataGridTextColumn Header="FilteredValue"

我正在编写一个简单的应用程序,在DataGrid上显示一些数据。数据只是一个测量值(浮点)和一个时间戳。自2000年以来,时间戳以秒为单位

我成功地完成了任务,但注意到显示数据网格需要很长时间(约1分钟)。大约有20000个数据。我不认为20000个数据由一个uint和一个浮动组成是那么糟糕。下一个请求是将时间显示为格式化时间,而不是自2000年以来的秒数。我这样做是通过使XAML看起来像这样:

<kit:DataGridTextColumn Header="FilteredValue" Binding="{Binding Path=FilteredValue}" />
<kit:DataGridTextColumn Header="Timestamp" Binding="{Binding Path=Timestamp, Converter={StaticResource TimeConverter}}" CanUserSort="False" />
这也很有效。然而,事实证明,一些原始数据可以是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分钟。我对此感到非常惊讶。是否只是额外的代码运行了23000次? 1.我该怎么办?我是否可以在XAML中执行某些操作,以便在不需要时不调用转换器? 2.当其中一个测量值(FilteredValues)为0xFFFFFFFF时,它将显示为NaN。这可能还可以,但最好只显示0xFFFFFFFF或“无数据”。我认为它被设置为NaN,因为底层数据类型是浮点型

有什么想法吗

谢谢, 戴夫

这是XAML。最后一个数据网格是我们感兴趣的。请注意,我甚至将“IsVirtualization”设置为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>

获取文件
分区1
分区3
分区2
分区4-标题信息
分区4-化学数据

由于该列是一个
DataGridTextColumn
,您只需在转换器中返回它,就可以使它显示0xFFFFFF

if ((uint)value == 0xFFFFFFFF)
{
    // don't bother to convert
    return "0xFFFFFFFF";
}
至于
DataGrid
的速度慢,默认情况下它应该使用
virtualizangstackpanel
,因此如果你没有改变这一点,那么它应该是相当快的,因为你只需要处理用户目前可见的
DataGridRows
。而且转换器中的代码几乎不需要时间。

因此,您的
DataGrid
运行缓慢的最可能原因可能是您将
ItemsPanel
更改为
virtualizangstackpanel
以外的其他内容,或者以某种方式禁用了虚拟化,但如果不了解
DataGrid
是如何定义的,则很难判断

编辑
DataGrid
完成加载后运行以下代码,例如在
DataGrid
Loaded
事件中。如果
MessageBox
显示大量(不应超过50),则说明问题的根源

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);
        }
    }
}
但是使用
网格
会非常快,因为
数据网格
的高度会受到限制,因此可以使用虚拟化

<Grid>
    <!-- Fast DataGrid with 20000+ items in ItemsSource -->
    <DataGrid ...>
</Grid>


探查器能帮你看到这里的瓶颈吗?谢谢Meleak,我尝试了你的一些建议。我在我的原始帖子中加入了XAML。这是最后一个拥有20000多个项目的DataGrid。我尝试了一些,但没有用。它仍然很慢。我确实广泛使用了StackPanels,但我想你指的是immediate Parent Panel?我还尝试了你的代码以查看行数。当我第一次启动应用程序时,它显示为“0”,然后在我获取文件时,代码从未被命中。除了“Loaded”之外,还有其他事件需要我查看吗?非常感谢,Dave@Dave:将
DataGrid
命名为某物,例如DataGrid(以防您尚未完成此操作)一旦加载了
DataGrid
,您就可以看到数据了,只需添加一个
按钮
,并在
按钮
点击事件中执行该代码。让我知道ResultMelak,我添加了按钮处理程序,得到了13080个计数,所以这似乎是问题所在,但我哪里出了问题?datagri有什么问题吗d在上面的XAML中命名为m_gridData?正如我所说,我的代码中充满了stackpanel,但我不想使用stackpanel(组织内容)与数据网格不兼容。谢谢,Dave@Dave:问题在于
StackPanel
。一个
StackPanel
总是给它的子对象他们要求的空间。因此,如果在
StackPanel
中添加一个
网格
,在
网格
中添加一个
DataGrid
,则,
<StackPanel>
    <!-- Slow DataGrid with 20000+ items in ItemsSource -->
    <DataGrid ...>
</StackPanel>
<Grid>
    <!-- Fast DataGrid with 20000+ items in ItemsSource -->
    <DataGrid ...>
</Grid>