首页 > 解决方案 > DataTable.Rows.Add() 将一行添加到 DataRowCollection.Count 但不是 DataRowCollection.List

问题描述

我正在构建一个 WPF MVVM 应用程序,并且我有一个绑定到 DataTable 的 DataGrid MapDataTable

我在这里填写列:

private void CreateDataTable()
{
      MapDataTable = new DataTable("MapDataTable");
      MapDataTable.Columns.Add("Name", typeof(string));
      MapDataTable.Columns.Add("Min", typeof(long));
      MapDataTable.Columns.Add("Max", typeof(long));

      MapDataTable.AcceptChanges();
}

我在这里填写行:

foreach (var item in data)
{
      DataRow dataRow = MapDataTable.NewRow();
      dataRow["Name"] = item.Name;
      dataRow["Min"] = item.Min;
      dataRow["Max"] = item.Max;

      MapDataTable.Rows.Add(dataRow);
}

MapDataTable.AcceptChanges();

DataTable temporaryDataTable = MapDataTable;
MapDataTable = null;
MapDataTable = temporaryDataTable;

地图页面:

<DataGrid
      Name="Map"
      AutoGenerateColumns="True"
      AutoGeneratingColumn="Map_AutoGeneratingColumn" 
      ItemsSource="{Binding MapDataTable.DefaultView}"/>

在最后一行之后进行细分后,我注意到Rows.Count增量(超过 10k 行),但Rows.List仍然为空。据我所知:

Count - 获取此集合中 DataRow 对象的总数。

List - 获取集合中的项目作为列表。

因此,行不会显示在 DataGrid 中。

有没有人遇到过这个?该行未添加到列表中的原因是什么?

编辑:我有一个用于其中一列的过滤器。列的标题由绑定到属性的 TextBox 组成FilterName

private string filterName = string.Empty;
public string FilterName
{
     get => filterName;
     set
     {
          SetProperty(ref filterName, value);
          MapDataTable.DefaultView.RowFilter = $"Name LIKE '%{FilterName}%'";
     }
}

我的代码曾经绑定到 a CollectionView,而不是 a DataTable,这就是为什么我不太熟悉RowFilter应该如何设置的原因,但我确信表达式。

标签: c#wpfdatagrid

解决方案


不要使用列名作为索引。这很难重构,例如在重命名列时。

然后确保在谓词 (FilterName) 为空或为空的情况下删除过滤器表达式。否则,您将看不到任何内容,因为所有值都无法满足过滤器表达式。

private void CreateDataTable()
{
      var newTable = new DataTable("MapDataTable");
      newTable.Columns.Add(nameof(MapData.Name), typeof(string));
      newTable.Columns.Add(nameof(MapData.Min), typeof(long));
      newTable.Columns.Add(nameof(MapData.Max), typeof(long));

      CreateRows(newTable, MapDataCollection);
      this.MapDataTable = newTable;
}

private void CreateRows(DataTable, dataTable, IEnumerable<MapData> mapDataItems)
{
  foreach (MapData mapData in mapDataItems)
  {
      DataRow dataRow = MapDataTable.NewRow();

        // It would be best to set the columns in a for-loop.
        // If you can't use a different data source you can use reflection to make
        // this part really "generic" and dynamic
        dataRow[0] = mapData.Name;
        dataRow[1] = mapData.Min;
        dataRow[2] = mapData.Max;

      MapDataTable.Rows.Add(dataRow);
    }
}

private string filterName = string.Empty;
public string FilterName
{
     get => filterName;
     set
     {
          SetProperty(ref filterName, value);
          MapDataTable.DefaultView.RowFilter = string.IsNullOrWhiteSpace(FilterName) 
            ? null 
            : $"Name LIKE '%{FilterName}%'";
     }
}

推荐阅读