Alexander Borochkin
Alexander Borochkin

Reputation: 4621

How to sort BindingList<T>?

I have several thousands MyClass objects stored in BindingList<MyClass>. I want to sort them by date property MyClass.dt.

Class BindingList doesn't support sorting directly. How I can sort BindingList<T> not making duplicate copies of all objects? I need to sort them as in ascending, as in descending order, please.

I don't need special class SortableBindingList as described in BindingList.Sort() to behave like a List.Sort(). I am searching for short solution in one o two lines of code.

Upvotes: 9

Views: 31872

Answers (3)

CW1255
CW1255

Reputation: 121

//Convert it to a data table, then the Automatic will work.
DataGridView.DataSource = ConvertToDataTable(MyList).DefaultView;

public DataTable ConvertToDataTable(IBindingList list)
{
   DataTable dt = new DataTable();

   if (list.Count > 0)
   {
      Type typ = list[0].GetType();

      PropertyInfo[] arrProps = typ.GetProperties();

      foreach (PropertyInfo pi in arrProps)
      {

         Type colType = pi.PropertyType;
         if (colType.IsGenericType)
         {
            colType = colType.GetGenericArguments()[0];
         }

         dt.Columns.Add(pi.Name, colType);
      }

      foreach (object obj in list)
      {
         DataRow dr = dt.NewRow();

         foreach (PropertyInfo pi in arrProps)
         {
            if (pi.GetValue(obj, null) == null)
               dr[pi.Name] = DBNull.Value;
            else
               dr[pi.Name] = pi.GetValue(obj, null);
         }

         dt.Rows.Add(dr);
      }
   }
   return dt;
}

Upvotes: -1

TnTinMn
TnTinMn

Reputation: 11801

A quick way to implement a Sort on a BindingList is to use the constructor that takes a backing IList< T > as its argument. You can use a List<T> as the backing and gain its Sort capabilities.

Per the documentation

Use this BindingList to create a BindingList that is backed by list, which ensures that changes to list are reflected in the BindingList.

If your MyClass was defined as:

internal class MyClass
{
    public MyClass(string name, Int32 num)
    {
        this.Name = name;
        this.Num = num;
    }
    public string Name {get; set;}
    public Int32 Num {get; set;}
}

then you could do something like this to sort it on the Num field.

private List<MyClass> backing;
private BindingList<MyClass> bl;

    private void InitializeBindingList()
        {
            backing = new List<MyClass>();
            bl = new BindingList<MyClass>(backing);
            bl.Add(new MyClass("a", 32));
            bl.Add(new MyClass("b", 23));
            bl.Add(new MyClass("c", 11));
            bl.Add(new MyClass("d", 34));
            bl.Add(new MyClass("e", 53));
        }

    private void SortBindingList()
        {
            backing.Sort((MyClass X, MyClass Y) => X.Num.CompareTo(Y.Num));
            // tell the bindinglist to raise a list change event so that 
            // bound controls reflect the new item order
            bl.ResetBindings();
        }
    }

You need to call BindingList.ResetBindings method after sorting the backing list to notify any bound controls that the BindingList has changed and to update the control.

Upvotes: 6

Igor
Igor

Reputation: 62213

Linq would work.

var sortedListInstance = new BindingList<MyClass>(unsortedListInstance.OrderBy(x => x.dt).ToList());

Keep in mind you get a shallow copy of the sorted list, not duplicate instances of MyClass.

Do not forget to include the namespace at the top of the code file System.Linq

Upvotes: 13

Related Questions