I am building a WPF MVVM application. I have a DataTable
, binded to a DataGrid
.
The columns of the data table in the beginning are 2 - Name and Value 1.
Name | Value 1
The data table is binded to an ObservableCollection
, called mapData
, which holds over 10k records.
When a user selects a ComboBox
I add dynamically a column, called Value 2.
Name | Value 1 | Value 2
These values both refer to the same name, so when I am adding the column, I use this approach:
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;
}
}
This works as expected, but it takes approximately 6.8s, which is too long.
Can I optimize it somehow?
I tried another approach - instead of iterating through the items of the ObservableCollection
, I iterate through the rows of the 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;
}
}
This takes approximately 7.1s, which is even longer.
Is there another way to do that?
CodePudding user response:
You can use a dictionary to speed this up
var dict = MapDataTable.ToDictionary(x => x.Field<string>("Name"));
foreach (var item in mapData)
{
if (dict.TryGetValue(item.Name, out var row))
{
row[2] = item.Value;
}
}
You can also do this in the opposite direction
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;
}
}
If there are multiple possible matches by Name
then you need to switch to ToLookup
or HashSet
CodePudding user response:
you can also do this in following way & it gives you more freedom and roam to change controls
<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>