Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keeping a DataGridView autosorted

I've got a DataGridView that is backed by a SortableBindingList as described by this article.

This is essentially a BindingList whose Data source is a list of custom objects. The underlying custom objects are updated programatically.

My SortableBindingList allows me to sort each column in Ascending or Descending order. I've done this by overloading the ApplySortCore method

protected override void ApplySortCore(PropertyDescriptor prop,
                                      ListSortDirection direction)

This works well for sorting when the column header is clicked on but won't sort automatically when cell in that column is programatically updated.

Has anyone else come up with a good solution for keeping a DataGridView sorted from programmatic updates of its underlying data source?

like image 602
chollida Avatar asked Jan 24 '13 02:01

chollida


2 Answers

Try to override OnDataSourceChanged Event

public class MyGrid : DataGridView {
    protected override void OnDataSourceChanged(EventArgs e)
    {
        base.OnDataSourceChanged(e);
        MyComparer YourComparer = null;
        this.Sort(YourComparer);
    }
}
like image 58
Eugene Avatar answered Oct 03 '22 19:10

Eugene


Consider this class:

public class MyClass : INotifyPropertyChanged
{
    private int _id;
    private string _value;

    public int Id
    {
        get
        {
            return _id;
        }
        set
        {
            PropertyChanged(this, new PropertyChangedEventArgs("Id"));
            _id = value;
        }
    }
    public string Value
    {
        get
        {
            return _value;
        }
        set
        {
            PropertyChanged(this, new PropertyChangedEventArgs("Value"));
            _value = value;
        }
    }
    public event PropertyChangedEventHandler PropertyChanged = new PropertyChangedEventHandler(OnPropertyChanged);

    private static void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        // optional code logic
    }
}

Add these methods to your sortable binding list:

public class SortableBindingList<T> : BindingList<T>, INotifyPropertyChanged
    where T : class
{
    public void Add(INotifyPropertyChanged item)
    {
        item.PropertyChanged += item_PropertyChanged;
        base.Add((T)item);
    }

    void item_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        this.PropertyChanged(sender, new PropertyChangedEventArgs(String.Format("{0}:{1}", sender, e)));
    }

    // other content in the method body
}

And use this sample methods in your form:

public Form1()
{
    InitializeComponent();
    source = new SortableBindingList<MyClass>();
    source.Add(new MyClass() { Id = 1, Value = "one test" });
    source.Add(new MyClass() { Id = 2, Value = "second test" });
    source.Add(new MyClass() { Id = 3, Value = "another test" });
    source.PropertyChanged += source_PropertyChanged;
    dataGridView1.DataSource = source;

}

void source_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    MessageBox.Show(e.PropertyName);
    dataGridView1.DataSource = source;
}

private void button1_Click(object sender, EventArgs e)
{
    ((MyClass)source[0]).Id++;
}
like image 37
Alex Filipovici Avatar answered Oct 03 '22 19:10

Alex Filipovici