WPF DataGrid работает ужасно медленно
Моя таблица
<DataGrid
x:Name="dataGrid"
AutoGenerateColumns="True"
EnableRowVirtualization="True"
EnableColumnVirtualization="True"
VirtualizingPanel.IsVirtualizing="True"
VirtualizingPanel.VirtualizationMode="Recycling"
ItemsSource="{Binding DisplayedData}"
ScrollViewer.ScrollChanged="DataGrid_ScrollChanged"
Style="{DynamicResource MyDataGrid}" />
Я конвертирую Lua таблицы в Task<List>, затем хочу вывести их в таблице:
private async Task DisplayLuaTable(dynamic luaTable, DataGrid dataGrid)
{
try
{
var dynamicList = await ConvertLuaTableToDynamicListAsync(luaTable);
pagedDataViewModel = new PagedDataViewModel(dynamicList);
Dispatcher.Invoke(() =>
{
dataGrid.AutoGenerateColumns = true;
Binding binding = new Binding("DataTable") { Source = pagedDataViewModel };
dataGrid.SetBinding(DataGrid.ItemsSourceProperty, binding); dataGrid.EnableRowVirtualization = true;
dataGrid.DataContext = pagedDataViewModel;
});
}
catch (Exception ex)
{
MessageBox.Show($"Error displaying Lua Table: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
PagedDataViewModel отвечает за ленивую загрузку данных:
public class PagedDataViewModel : INotifyPropertyChanged
{
private int pageSize = 50;
private int currentPage = 1;
private List<dynamic> allData;
private DataTable dataTable;
public PagedDataViewModel(List<dynamic> allData)
{
this.allData = allData;
LoadData();
}
private void LoadData()
{
int startIndex = (currentPage - 1) * pageSize;
int endIndex = Math.Min(startIndex + pageSize, allData.Count);
DataTable newDataTable = ConvertDynamicListToDataTable(allData.GetRange(startIndex, endIndex - startIndex));
if (dataTable == null)
{
dataTable = newDataTable;
}
else
{
DataTable combinedDataTable = new DataTable();
foreach (DataColumn column in dataTable.Columns)
{
combinedDataTable.Columns.Add(column.ColumnName, column.DataType);
}
foreach (DataRow row in dataTable.Rows)
{
combinedDataTable.ImportRow(row);
}
foreach (DataRow row in newDataTable.Rows)
{
combinedDataTable.ImportRow(row);
}
dataTable = combinedDataTable;
}
OnPropertyChanged(nameof(DataTable));
}
private async Task LoadDataAsync()
{
int startIndex = (currentPage - 1) * pageSize;
int endIndex = Math.Min(startIndex + pageSize, allData.Count);
DataTable newDataTable = await Task.Run(() => ConvertDynamicListToDataTable(allData.GetRange(startIndex, endIndex - startIndex)));
if (dataTable == null)
{
dataTable = newDataTable;
}
else
{
DataTable combinedDataTable = new DataTable();
foreach (DataColumn column in dataTable.Columns)
{
combinedDataTable.Columns.Add(column.ColumnName, column.DataType);
}
foreach (DataRow row in dataTable.Rows)
{
combinedDataTable.ImportRow(row);
}
foreach (DataRow row in newDataTable.Rows)
{
combinedDataTable.ImportRow(row);
}
dataTable = combinedDataTable;
}
OnPropertyChanged(nameof(DataTable));
}
public async Task LoadNextPageAsync()
{
if (currentPage * pageSize < allData.Count)
{
currentPage++;
await LoadDataAsync();
}
}
public DataTable DataTable => dataTable;
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
Debug.WriteLine($"Property {propertyName} changed.");
}
private DataTable ConvertDynamicListToDataTable(List<dynamic> dynamicList)
{
try
{
DataTable dataTable = new DataTable();
if (dynamicList.Count > 0)
{
var firstObject = dynamicList[0] as IDictionary<string, object>;
if (firstObject != null)
{
foreach (var propertyName in firstObject.Keys)
{
// Добавьте проверку наличия колонки перед добавлением
if (!dataTable.Columns.Contains(propertyName))
{
dataTable.Columns.Add(propertyName, typeof(object));
}
}
foreach (var dynamicObject in dynamicList)
{
var dataRow = dataTable.NewRow();
var currentObject = dynamicObject as IDictionary<string, object>;
foreach (var propertyName in currentObject.Keys)
{
if (dataTable.Columns.Contains(propertyName))
{
dataRow[propertyName] = currentObject[propertyName];
}
}
dataTable.Rows.Add(dataRow);
}
}
}
return dataTable;
}
catch (Exception ex)
{
return null;
}
}
}
Он вызывается при скорлле и подгружает данные в таблицу
private async void DataGrid_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
if (e.VerticalChange > 0 && e.VerticalOffset + e.ViewportHeight == e.ExtentHeight)
{
await pagedDataViewModel.LoadNextPageAsync();
}
}
само выполнение
await pagedDataViewModel.LoadNextPageAsync();
происходит довольно быстро, но при каждом его вызове UI начинает жутко зависать. Сама таблица начинает зависать уже при 100-200 рядках.
Я пробовал отключать\включать виртуализацию, это ничего не меняет.
Очень надеюсь на помощь или совет в каком направлении искать проблему,
Спасибо