.Net Grid enables multiple row sorting upon data changes in real-time, taking into account sorting direction, grouping rules and data hierarchy.

On programming side it can be done via Column.SortDirection property. This property sets the sorting direction or turns it off. When you sequentially set this property for several columns, you enable multiple sorting in the data grid. Every column that is involved in the sorting has its own zero-based level. Information about all sorted columns can be retrieved via Header.Sort property. It’s important to mention that column visibility doesn’t affect data sorting. It means that rows will be sorted without regard to column visibility or to whether column is grouped or not.

WIthout sorting, all grid rows are automatically indexed thereby increasing grid performance. When sorting is used for some columns, all data is sorted in ordered sequence according to sorting rules and data hierarchy. This way, when you add new data into the data grid, it is automatically added to the right position according to the above rules. When you call Row.Update() method, the .Net Grid searches a new position for the row and moves it to the right position. When you use an event-driven model (i.e. when you use the INotifyPropertyChanged interface implementation), Row.Update() method is invoked systematically. In other words, when sorting is enabled, the .Net Grid constantly stores data in ordered sequence. In addition to that, the .Net Grid properly processes data changes in several rows including processing of separate threads. You won’t find some kind of Sort() method in the .Net Grid, because the data is always in the ordered sequence.

Non-event model

C# Copy imageCopy
public void NonEventModelSorting(Grid grid)
{
    //Initialize the grid
    grid.Headers.Add(new Header());
    grid.Headers[0].Add(new Column("Name"));
    grid.Headers[0].Add(new Column("Color"));
    grid.Headers[0].Add(new Column("Price"));

    grid.Headers[0]["Price"].SortDirection = SortDirection.Descending;

    //Populate the grid
    grid.Rows.Add(new object[] { "Mercedes", Color.Black, 25000d });
    grid.Rows.Add(new object[] { "BMW", Color.White, 35000d });

    //The first row is "BMW"
    Assert.AreEqual("BMW", grid.Rows[0]["Name"].Value);

    //Cut off the BMW's price
    grid.Rows[0]["Price"].Value = 24000d;

    //The first row is "Mercedes"
    Assert.AreEqual("Mercedes", grid.Rows[0]["Name"].Value);
}

Event-driven model

The same example in the event-driven model:

C# Copy imageCopy
//Some data object
public class Car : INotifyPropertyChanged
{
    private readonly string name;
    private readonly Color color;
    private double price;

    public Car(string name, Color color, double price)
    {
        this.name = name;
        this.color = color;
        this.price = price;
    }

    public string Name
    {
        get { return name; }
    }

    public Color Color
    {
        get { return color; }
    }

    public double Price
    {
        get { return price; }
        set
        {
            if (price != value)
            {
                price = value;
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs("Price"));
                }
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

public void EventDrivenModelSorting(Grid grid)
{
    //Initialize the grid
    grid.Headers.Add(new Header());
    grid.Headers[0].Add(new Column("Name"));
    grid.Headers[0].Add(new Column("Color"));
    grid.Headers[0].Add(new Column("Price"));

    grid.Headers[0]["Price"].SortDirection = SortDirection.Descending;

    Car mercedes = new Car("Mercedes", Color.Black, 25000);
    Car bmw = new Car("BMW", Color.White, 35000);

    //Populate the grid
    grid.Rows.Add(mercedes);
    grid.Rows.Add(bmw);

    //The first row is "BMW"
    Assert.AreEqual("BMW", grid.Rows[0]["Name"].Value);

    //Cut off the BMW's price. 
    //The car is your business logic and you can place it in any assembly that doesn't need to have references to Dapfor assemblies!
    bmw.Price = 24000;

    //The first row is "Mercedes"
    Assert.AreEqual("Mercedes", grid.Rows[0]["Name"].Value);
}

Performance

It may seem, that regular invocation of the Row.Update() method, especially via INotifyPropertyChanged interface, is quite resource-intensive. However, this presumption is wrong. First of all, if new position search returns previous position of the row, this means that no resources will be wasted on row moving. Secondly, moving the row in a sorted collection is a simple operation. The search itself takes ln(N) iterations, where N – is the number of rows in the data grid. In traditional data grids, if data is not stored in sorted order, you have to invoke Collection.Sort() method for the whole set every time the data is changed. Accordingly, the cost of this operation even with the most efficient algorithms is – N * ln(N) iterations. It means that the number of operations directly depends on the number of the rows in the data grid. In actual practice, .Net Grid containing 2,000 rows is able to process more than 3,000 sorting operations per second!