Friday, December 17, 2021

Improve performance when mass selecting rows on XamDataGrid

I wrote a custom control to allow mass selection of rows in a XamDataGrid which runs slowly when there are more than a few hundred rows. It seems the act of setting a record's IsSelected flag takes about one millisecond which adds up for grids with a lot of rows.

        private void One_Click(object sender, RoutedEventArgs e)
        {
            foreach (Record r in TheGrid.Records)
                r.IsSelected = true;
        }

The XamDataGrid has a SelectedItems property which has a Records property. If I clear this property the grid updates instantly. The property has an AddRange method that takes an array of Records. AddRange tends to be very fast - Hmmmm.

This code could be cleaner, but it's very fast. I would prefer to populate a List of Records and use the ToArray method.

        private void Range_Click(object sender, RoutedEventArgs e)
        {
            DataRecord[] records = new DataRecord[TheGrid.Records.Count];
            TheGrid.Records.CopyTo(records, 0);
            TheGrid.SelectedItems.Records.AddRange(records);
        }

Here is some XAML and code that demonstrates the performance difference. Please forgive the non MVVM solution, it's Friday afternoon and I have stuff to do before I go home for the weekend.

<Window x:Class="SelectAll.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:igDP="http://infragistics.com/DataPresenter"
        xmlns:local="clr-namespace:SelectAll"
        mc:Ignorable="d"
        SizeToContent="WidthAndHeight"
        DataContext="{Binding RelativeSource={RelativeSource Self}}"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="auto"/>
        </Grid.RowDefinitions>
 
        <igDP:XamDataGrid Grid.Row="0" Grid.Column="0" Name="TheGrid" Height="400" DataSource="{Binding Items}">
            <igDP:XamDataGrid.FieldSettings>
                <igDP:FieldSettings AllowEdit="False" CellClickAction="SelectRecord"/>
            </igDP:XamDataGrid.FieldSettings>
        </igDP:XamDataGrid>
        <StackPanel Grid.Row="1" Grid.Column="0" Orientation="Horizontal">
            <Button Content="Select one at a time" Click="One_Click"/>
            <Button Content="Select range" Click="Range_Click"/>
            <Button Content="Clear" Click="Clear_Click"/>
        </StackPanel>
    </Grid>
</Window>

using Infragistics.Windows.DataPresenter;
using System.Collections.Generic;
using System.Windows;
 
namespace SelectAll
{
    public class cItem
    {
        public int ID { get; set; }
        public string Code { get; set; }
        public string Description { get; set; }
    }
    public partial class MainWindow : Window
    {
        public List<cItem> Items { get; set; }
        public MainWindow()
        {
            PopulateItems();
            InitializeComponent();
        }
 
        private void PopulateItems()
        {
            Items = new List<cItem>();
            for (int i = 1; i < 5000; i++)
                Items.Add(new cItem() { ID = i, Code = "Code " + i, Description = "Description " + i });
        }
        private void One_Click(object sender, RoutedEventArgs e)
        {
            foreach (Record r in TheGrid.Records)
                r.IsSelected = true;
        }
 
        private void Range_Click(object sender, RoutedEventArgs e)
        {
            DataRecord[] records = new DataRecord[TheGrid.Records.Count];
            TheGrid.Records.CopyTo(records, 0);
            TheGrid.SelectedItems.Records.AddRange(records);
        }
 
        private void Clear_Click(object sender, RoutedEventArgs e)
        {
            TheGrid.SelectedItems.Records.Clear();
        }
    }
}

  


On my computer, selecting all the rows one at a time takes 14 seconds. Selecting them using AddRange is too quick to measure.




No comments:

Post a Comment