Home > Software design >  Find and edit row in DataTable speed optimization WPF DataGrid
Find and edit row in DataTable speed optimization WPF DataGrid

Time:10-06

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>
  • Related