我正在构建一个WPF MVVM应用程序。我有一个DataTable
,和一个DataGrid
结合。
开头数据表的列为2 - Name和Value 1.
名称|值1
数据表绑定到一个ObservableCollection
,称为mapData
,它拥有超过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>