在 DataTable 中查找和编辑行速度优化 WPF DataGrid
Find and edit row in DataTable speed optimization WPF DataGrid
我正在构建 WPF MVVM 应用程序。我有一个 DataTable
,绑定到一个 DataGrid
。
开头的数据 table 的列是 2 - Name 和 Value 1。
姓名 |值 1
数据 table 绑定到名为 mapData
的 ObservableCollection
,它包含超过 10k 条记录。
当用户选择 ComboBox
我动态添加一列,称为值 2。
姓名 |值 1 |值 2
这些值都引用相同的名称,所以当我添加列时,我使用这种方法:
foreach (var item in mapData)
{
DataRow row = MapDataTable.AsEnumerable().Where(x => x.Field<string>("Name") == item.Name).First();
if (row != null) //it should be always true, but just in case
{
row[2] = item.Value;
}
}
这按预期工作,但大约需要 6.8 秒,这太长了。
我能以某种方式优化它吗?
我尝试了另一种方法 - 我没有遍历 ObservableCollection
的项目,而是遍历了 DataTable
.
的行
foreach (DataRow row in MapDataTable.Rows)
{
if (mapData.Any(x => x.Name == row.Field<string>("Name"))) //should always be true
{
var item = mapData.Where(x => x.Name == row.Field<string>("Name")).First();
row[2] = item.Value;
}
}
这大约需要 7.1 秒,甚至更长。
还有其他方法吗?
您可以使用字典来加快速度
var dict = MapDataTable.Rows.Cast<DataRow>().ToDictionary(x => x.Field<string>("Name"));
foreach (var item in mapData)
{
if (dict.TryGetValue(item.Name, out var row))
{
row[2] = item.Value;
}
}
反方向也可以
var dict = mapData.ToDictionary(x => x.Name);
foreach (DataRow row in MapDataTable.Rows)
{
if (dict.TryGetValue(row.Field<string>("Name"), out var item))
{
row[2] = item.Value;
}
}
如果 Name
有多个可能的匹配项,那么您需要切换到 ToLookup
或 HashSet
您也可以按照以下方式执行此操作 & 它为您提供更多自由和漫游来更改控件
<ItemsControl
ItemsSource="{Binding SourceList}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.Template>
<ControlTemplate>
<Border>
<ScrollViewer>
<ItemsPresenter />
</ScrollViewer>
</Border>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Button Content="{Binding Value}">
</Button>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
我正在构建 WPF MVVM 应用程序。我有一个 DataTable
,绑定到一个 DataGrid
。
开头的数据 table 的列是 2 - Name 和 Value 1。
姓名 |值 1
数据 table 绑定到名为 mapData
的 ObservableCollection
,它包含超过 10k 条记录。
当用户选择 ComboBox
我动态添加一列,称为值 2。
姓名 |值 1 |值 2
这些值都引用相同的名称,所以当我添加列时,我使用这种方法:
foreach (var item in mapData)
{
DataRow row = MapDataTable.AsEnumerable().Where(x => x.Field<string>("Name") == item.Name).First();
if (row != null) //it should be always true, but just in case
{
row[2] = item.Value;
}
}
这按预期工作,但大约需要 6.8 秒,这太长了。
我能以某种方式优化它吗?
我尝试了另一种方法 - 我没有遍历 ObservableCollection
的项目,而是遍历了 DataTable
.
foreach (DataRow row in MapDataTable.Rows)
{
if (mapData.Any(x => x.Name == row.Field<string>("Name"))) //should always be true
{
var item = mapData.Where(x => x.Name == row.Field<string>("Name")).First();
row[2] = item.Value;
}
}
这大约需要 7.1 秒,甚至更长。
还有其他方法吗?
您可以使用字典来加快速度
var dict = MapDataTable.Rows.Cast<DataRow>().ToDictionary(x => x.Field<string>("Name"));
foreach (var item in mapData)
{
if (dict.TryGetValue(item.Name, out var row))
{
row[2] = item.Value;
}
}
反方向也可以
var dict = mapData.ToDictionary(x => x.Name);
foreach (DataRow row in MapDataTable.Rows)
{
if (dict.TryGetValue(row.Field<string>("Name"), out var item))
{
row[2] = item.Value;
}
}
如果 Name
有多个可能的匹配项,那么您需要切换到 ToLookup
或 HashSet
您也可以按照以下方式执行此操作 & 它为您提供更多自由和漫游来更改控件
<ItemsControl
ItemsSource="{Binding SourceList}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.Template>
<ControlTemplate>
<Border>
<ScrollViewer>
<ItemsPresenter />
</ScrollViewer>
</Border>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Button Content="{Binding Value}">
</Button>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>