I am building a WPF MVVM application and I have a DataGrid, which is binded to the DataTable MapDataTable
.
I am filling the columns here:
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();
}
I am filling the rows here:
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;
Map page:
<DataGrid
Name="Map"
AutoGenerateColumns="True"
AutoGeneratingColumn="Map_AutoGeneratingColumn"
ItemsSource="{Binding MapDataTable.DefaultView}"/>
After putting a breakdown after the last line, I noticed, that the Rows.Count
increments (more than 10k rows), but Rows.List
remains null. As far as I know:
Count - Gets the total number of DataRow objects in this collection.
List - Gets the items of the collection as a list.
Because of this, the rows are not displayed in the DataGrid.
Has anyone come across this? What is the reason the row is not added to the list?
EDIT:
I have a filter for one of the columns. The header of the column consists of a TextBox which is binded to the property FilterName
.
private string filterName = string.Empty;
public string FilterName
{
get => filterName;
set
{
SetProperty(ref filterName, value);
MapDataTable.DefaultView.RowFilter = $"Name LIKE '%{FilterName}%'";
}
}
My code used to bind to a CollectionView
, not to a DataTable
, that's why I am not very familiar with how the RowFilter
should be set, but I am sure of the expression.
CodePudding user response:
Don't use the column names as index. This is difficult to refactor e.g., when renaming a column.
Then make sure to remove the filter expression in case the predicate (FilterName) is null or empty. Otherwise you won't see anything as all values fail to satisfy the filter expression.
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}%'";
}
}
CodePudding user response:
According to the C# Reference Source found here, it appears that the issue is that "list.Add()" is only ever called in one specific case internally that I could find which is list.Add(null);
The source it is taken from is below:
internal void DiffInsertAt(DataRow row, int pos) {
if ((pos < 0) || (pos == list.Count)) {
table.AddRow(row, pos >-1? pos 1 : -1);
return;
}
if (table.NestedParentRelations.Length > 0) { // get in this trouble only if table has a nested parent
// get into trouble if table has JUST a nested parent? how about multi parent!
if (pos < list.Count) {
if (list[pos] != null) {
throw ExceptionBuilder.RowInsertTwice(pos, table.TableName);
}
list.RemoveAt(pos);
nullInList--;
table.InsertRow(row, pos 1, pos);
}
else {
while (pos>list.Count) {
list.Add(null); // <-- here
nullInList ;
}
table.AddRow(row, pos 1);
}
}
else {
table.InsertRow(row, pos 1, pos > list.Count ? -1 : pos);
}
}
I can't find any other instance where the List
property is actually used to add entries.
What this means is that you might just have to use your own generic method if you wanna have a ToList()
method for your DataTable
. If that wasn't the case, then I don't think there is anything else to do in this case.