2013-10-01 8 views
3

몇 가지 권장 사항에서 DataGridView.Rows.Add(...) 대신 DataSourceDataGridView에 할당하기 시작했습니다. 내 데이터 소스가 이미 많이 변경되지 않은 큰 목록이므로 편리합니다. 그러나 DataSource 지정을 사용하면 열을 정렬 할 수 없게됩니다. 할당 된 데이터 소스로 DataGridView에서 정렬을 어떻게 활성화합니까?

class MyGridView : DataGridView 
{ 
    private List<Person> m_personList; 

    private class Person 
    { 
     public string FirstName { get; set; } 
     public string LastName { get; set; } 
     public Person(string first, string last) 
     { 
      FirstName = first; 
      LastName = last; 
     } 
    } 

    public MyGridView() 
    { 
     /* ...initialise stuff... */ 
     m_personList.Add(new Person("Kate", "Smith")); 
     m_personList.Add(new Person("Bill", "Davids")); 
     m_personList.Add(new Person("Ann", "Roth")); 

     this.DataSource = m_personList; 
    } 
} 

는 또한 BindingList<Person>에 의해 BindingSource에 의해 List<Person>를 교체했지만, 그 어느 것도 중요 할 것 같다.

this.SortCompare += MyGridView_SortCompare; 

private void MyGridView_SortCompare(object sender, EventArgs e) 
{ 
    /* ...Compare method...*/ 
} 

도 추가로 시도해 보았습니다. 데이터 소스로 정렬 할 수있는 다른 방법이 있습니까?

참고 : 내 데이터 소스는 SQL (필수)이 아니며 단지 List입니다.

+0

이 당신이 http://msdn.microsoft.com/en-us/library/system.web.ui 찾고있는 무엇인가 :

의 DataTable에 목록을 변환하는 경우, 문서를 참조하십시오. webcontrols.gridview.sort.aspx? –

+0

나는 확실히 모르겠다. 그러나 나는 그것이 있다고 생각하지 않는다. DataSource를 사용하지 않고 모든 행을 추가 할 때처럼 열 머리글을 클릭하면 모든 것이 정렬됩니다. 복잡한 Sort 메서드를 구현하려고하지 않습니다. – Yellow

+0

위의 링크는 매우 단순한'MyGridView.Sort ("ColumnName", SortDirection.Ascending);','RowDataBound' 안에 넣거나 새 행을 추가 할 때마다 위치시킵니다. –

답변

6

데이터 원본을 정렬 (IBindingList 및 IBindingListView)을 지원하는 목록으로 강제 변환해야합니다. 그러면 상자에서 작동합니다. 웹에 대한 예제가 많이 있는데, 이것은 내가 과거에 사용했던 하나입니다

// usage: 
// var sortableList = new SortableList(m_personList); 
// dgv.DataSource = m_sortableList; 


/// <summary> 
/// Suitable for binding to DataGridView when column sorting is required 
/// </summary> 
/// <typeparam name="T"></typeparam> 
public class SortableList<T> : BindingList<T>, IBindingListView 
{ 
    private PropertyComparerCollection<T> sorts; 

    public SortableList() 
    { 
    } 

    public SortableList(IEnumerable<T> initialList) 
    { 
     foreach (T item in initialList) 
     { 
      this.Add(item); 
     } 
    } 

    public SortableList<T> ApplyFilter(Func<T, bool> func) 
    { 
     SortableList<T> newList = new SortableList<T>(); 
     foreach (var item in this.Where(func)) 
     { 
      newList.Add(item); 
     } 

     return newList; 
    } 

    protected override bool IsSortedCore 
    { 
     get { return this.sorts != null; } 
    } 

    protected override bool SupportsSortingCore 
    { 
     get { return true; } 
    } 

    protected override ListSortDirection SortDirectionCore 
    { 
     get 
     { 
      return this.sorts == null 
         ? ListSortDirection.Ascending 
         : this.sorts.PrimaryDirection; 
     } 
    } 

    protected override PropertyDescriptor SortPropertyCore 
    { 
     get 
     { 
      return this.sorts == null ? null : this.sorts.PrimaryProperty; 
     } 
    } 

    public void ApplySort(ListSortDescriptionCollection 
           sortCollection) 
    { 
     bool oldRaise = RaiseListChangedEvents; 
     RaiseListChangedEvents = false; 
     try 
     { 
      PropertyComparerCollection<T> tmp 
       = new PropertyComparerCollection<T>(sortCollection); 
      List<T> items = new List<T>(this); 
      items.Sort(tmp); 
      int index = 0; 
      foreach (T item in items) 
      { 
       SetItem(index++, item); 
      } 
      this.sorts = tmp; 
     } 
     finally 
     { 
      RaiseListChangedEvents = oldRaise; 
      ResetBindings(); 
     } 
    } 

    public bool Exists(Predicate<T> func) 
    { 
     return new List<T>(this).Exists(func); 
    } 

    string IBindingListView.Filter 
    { 
     get { throw new NotImplementedException(); } 
     set { throw new NotImplementedException(); } 
    } 

    void IBindingListView.RemoveFilter() 
    { 
     throw new NotImplementedException(); 
    } 

    ListSortDescriptionCollection IBindingListView.SortDescriptions 
    { 
     get { return (this.sorts == null ? null : this.sorts.Sorts); } 
    } 

    bool IBindingListView.SupportsAdvancedSorting 
    { 
     get { return true; } 
    } 

    bool IBindingListView.SupportsFiltering 
    { 
     get { return false; } 
    } 

    protected override void RemoveSortCore() 
    { 
     this.sorts = null; 
    } 

    protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction) 
    { 
     ListSortDescription[] arr = { new ListSortDescription(prop, direction) }; 
     ApplySort(new ListSortDescriptionCollection(arr)); 
    } 
} 

public class PropertyComparerCollection<T> : IComparer<T> 
{ 
    private readonly PropertyComparer<T>[] comparers; 

    private readonly ListSortDescriptionCollection sorts; 

    public PropertyComparerCollection(ListSortDescriptionCollection 
              sorts) 
    { 
     if (sorts == null) 
     { 
      throw new ArgumentNullException("sorts"); 
     } 
     this.sorts = sorts; 
     List<PropertyComparer<T>> list = new 
      List<PropertyComparer<T>>(); 

     foreach (ListSortDescription item in sorts) 
     { 
      list.Add(new PropertyComparer<T>(item.PropertyDescriptor, 
              item.SortDirection == ListSortDirection.Descending)); 
     } 

     this.comparers = list.ToArray(); 
    } 

    public ListSortDescriptionCollection Sorts 
    { 
     get { return this.sorts; } 
    } 

    public PropertyDescriptor PrimaryProperty 
    { 
     get 
     { 
      return this.comparers.Length == 0 
         ? null 
         : this.comparers[0].Property; 
     } 
    } 

    public ListSortDirection PrimaryDirection 
    { 
     get 
     { 
      return this.comparers.Length == 0 
         ? ListSortDirection.Ascending 
         : this.comparers[0].Descending 
          ? ListSortDirection.Descending 
          : ListSortDirection.Ascending; 
     } 
    } 

    int IComparer<T>.Compare(T x, T y) 
    { 
     int result = 0; 
     foreach (PropertyComparer<T> t in this.comparers) 
     { 
      result = t.Compare(x, y); 
      if (result != 0) 
      { 
       break; 
      } 
     } 
     return result; 
    } 
} 

public class PropertyComparer<T> : IComparer<T> 
{ 
    private readonly bool descending; 

    private readonly PropertyDescriptor property; 

    public PropertyComparer(PropertyDescriptor property, bool descending) 
    { 
     if (property == null) 
     { 
      throw new ArgumentNullException("property"); 
     } 

     this.descending = descending; 
     this.property = property; 
    } 

    public bool Descending 
    { 
     get { return this.descending; } 
    } 

    public PropertyDescriptor Property 
    { 
     get { return this.property; } 
    } 

    public int Compare(T x, T y) 
    { 
     int value = Comparer.Default.Compare(this.property.GetValue(x), 
              this.property.GetValue(y)); 
     return this.descending ? -value : value; 
    } 
} 
+0

아, 고마워. 이제 뭘 찾아야할지, 갑자기 어디에서나 답을 찾는다. :) 나는 내 질문을 중복으로 표시 할 것이다. – Yellow

+0

그런데 어떤 라이브러리를 사용해야합니까? 'Func '와'this.Where (func)'함수가 인식되지 않아 어디서 찾을 수 없는지 알아 냈습니다. – Yellow

+0

'using System.Linq; ' – stuartd

1

대체는 DataTable을로 목록을 변환 한 다음에 BindingSource를 통해 DataGridView에 해당 DataTable에 바인딩하는 것입니다. 이렇게하면 DataGridView는 DataTable에서 사용할 수있는 정렬 옵션을 상속받습니다. How to fill a datatable with List<T>