2

我有一个非常大的逗号分隔文本文件。我需要在 WPF Datagrid 中显示它,哪种方法会导致将所有数据加载到网格中的最高性能?我只知道两种方法:

  • 使用数据表,并将每一行添加为行(看起来有点矫枉过正)
  • 使用 ObservableCollection,为每一行创建对象(看起来有点矫枉过正)

是否有第三种方法来填充 Datagrid,这将提供更高的性能?

4

2 回答 2

2

取决于您打算如何处理数据。如果数据是只读的,您可以定义一个 List 并将其设置为数据网格的 ItemsSource。然后数据网格将自动创建所有行来表示列表中的项目。

如果要操作数据,您可以使用 BindingList<> 或 ObservableCollection<>。

“为每一行创建对象”如何过度杀伤?您必须将一行/行数据表示为一个对象。这只是常识,不可能以任何其他方式做到这一点。

基本上,如果性能是您所追求的,那么数据网格的 ItemsSource 必须尽可能轻。如果您不打算使用它的所有功能,则 DataTable 可能是一种矫枉过正。另一方面, List<> 的重量尽可能轻。

另请注意,WPF 数据网格默认使用虚拟化,这也有助于提高性能。有一些警告,比如不要将数据网格放在堆栈面板中,否则虚拟化效果会消失 - 你可以用谷歌搜索。

最后一件事,根据我的经验,.NET4 WPF 内置数据网格有一个严重的设计错误。基本上每个 DataGridRow 都会消耗 1MB 的内存,即使是最简单的数据也是如此。使用虚拟化并且只显示 30 行,这并不是什么大问题——只消耗了 30MB 的内存。但是取一千行,关闭虚拟化,内存消耗是3GB!!!!相比之下,WinForm datagridview 使用相同的数据消耗的内存要少 10 倍以上。即使禁用了虚拟化,一千行也只需要 30MB ......

我在 Connect 中打开了一个关于此的错误,但专业专家尚未调查此问题。不确定 WPF 工具包数据网格的行为是否更好......

于 2010-09-24T06:24:36.343 回答
0

如果使用 OleDb 加载逗号分隔的文件,则可以绑定到 DataView。
注意:我没有测试大型数据集。

这是到 DataGrid 的绑定:

<Window x:Class="DatagridBackgroundWorker.Views.MainView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:WpfToolkit="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit" 
    Loaded="Window_Loaded"
    Title="Main Window" Height="400" Width="800">
  <DockPanel>
    <Grid>
        <WpfToolkit:DataGrid  
            ItemsSource="{Binding Path=GridData, Mode=OneWay}" >
        </WpfToolkit:DataGrid>
    </Grid>
  </DockPanel>
</Window>

这是视图模型:

public class MainViewModel : ViewModelBase
{
  public MainViewModel()
  {
     // name of the file
     string fileName = "MyData.txt";

     // location of the file
     string filePath = Environment.CurrentDirectory;
     string connection = @"Provider=Microsoft.Jet.OleDb.4.0; Data Source = " +
                         filePath +
                         ";Extended Properties=\"Text;HDR=Yes;FMT=Delimited\"";

     OleDbConnection conn = new OleDbConnection(connection);
     conn.Open();
     OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * FROM [" + fileName + "]", conn);
     adapter.Fill(_ds);
  }

  private DataSet _ds = new DataSet("MyDataSet");
  public DataView GridData
  {
     get
     {
        return _ds.Tables[0].DefaultView;
     }
  }
}

这是我使用的数据文件:

name,site,extra
jeff,codinghorror,stackoverflow
joel,joelonsoftware,stackoverflow
zamboni,secondbeach,stackoverflow
于 2010-09-24T15:17:32.283 回答