Как отсортировать столбец DataBound в DataGridView по щелчку заголовка столбца? - PullRequest
3 голосов
/ 03 июня 2011

Я считаю, что это должно быть обработано автоматически. Я связываю DataGridView с массивом объектов:

public class Entity {    
    public string Name { get; set; }     
    public int PrimaryKey { get; set; }
}

Связывание сетки:

public void BindGrid(Entity[] entities) {
    grdEntities.DataSource = entities;
}

Когда я щелкаю заголовок столбца в столбце «Имя», ничего не происходит, даже если для SortMode установлено значение «Автоматически». Глиф сортировки также отсутствует в заголовке столбца.

Я пытался привязать IBindingList, а также IList, но это не сработало.

Я надеюсь, что есть простое, элегантное решение с установкой свойств для DataGridView или DataGridViewColumn вместо необходимости создавать новый класс для поддержки сортировки. Что я должен сделать, чтобы поддержать сортировку столбца, щелкнув заголовок в DataBound DataGridView?

Ответы [ 2 ]

5 голосов
/ 03 июня 2011

Я создал новый интерфейс на основе IComparer, который позволяет указывать как столбец, так и направление. Я сделал это только потому, что мне нужно, чтобы мой код сортировки был как можно более универсальным - у меня есть ДВА сетки, которые нужно сортировать таким образом, и я не хочу поддерживать код дважды. Вот интерфейс, довольно простой:

   public interface IByColumnComparer : IComparer
   {
      string SortColumn { get; set; }
      bool SortDescending { get; set; }
   }

Очевидно, что если вы не беспокоитесь о сохранении общих свойств (вам, вероятно, следует), тогда это не является строго обязательным. Затем я создал новый класс, основанный на BindingList <>. Это позволило мне переопределить код сортировки и предоставить свой собственный IByColumnComparer для каждого столбца, что позволило обеспечить необходимую гибкость. Проверьте это:

public class SortableGenericCollection<T> : BindingList<T>
{
  IByColumnComparer GenericComparer = null; 

  public SortableGenericCollection(IByColumnComparer SortingComparer)
  {
     GenericComparer = SortingComparer;
  }


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

  protected override bool IsSortedCore
  {
     get
     {
        for (int i = 0; i < Items.Count - 1; ++i)
        {
           T lhs = Items[i];
           T rhs = Items[i + 1];
           PropertyDescriptor property = SortPropertyCore;
           if (property != null)
           {
              object lhsValue = lhs == null ? null :
              property.GetValue(lhs);
              object rhsValue = rhs == null ? null :
              property.GetValue(rhs);
              int result;
              if (lhsValue == null)
              {
                 result = -1;
              }
              else if (rhsValue == null)
              {
                 result = 1;
              }
              else
              {
                 result = GenericComparer.Compare(lhs, rhs); 
              }
              if (result >= 0)
              {
                 return false;
              }
           }
        }
        return true;
     }
  }

  private ListSortDirection sortDirection;
  protected override ListSortDirection SortDirectionCore
  {
     get
     {
        return sortDirection;
     }
  }

  private PropertyDescriptor sortProperty;
  protected override PropertyDescriptor SortPropertyCore
  {
     get
     {
        return sortProperty;
     }
  }

  protected override void ApplySortCore(PropertyDescriptor prop,
  ListSortDirection direction)
  {
     sortProperty = prop;
     sortDirection = direction;

     GenericComparer.SortColumn = prop.Name;
     GenericComparer.SortDescending = direction == ListSortDirection.Descending ? true : false;

     List<T> list = (List<T>)Items;
     list.Sort(delegate(T lhs, T rhs)
     {
        if (sortProperty != null)
        {
           object lhsValue = lhs == null ? null :
           sortProperty.GetValue(lhs);
           object rhsValue = rhs == null ? null :
           sortProperty.GetValue(rhs);
           int result;
           if (lhsValue == null)
           {
              result = -1;
           }
           else if (rhsValue == null)
           {
              result = 1;
           }
           else
           {
              result = GenericComparer.Compare(lhs, rhs);
           }
           return result;
        }
        else
        {
           return 0;
        }
     });
  }

  protected override void RemoveSortCore()
  {
     sortDirection = ListSortDirection.Ascending;
     sortProperty = null;
  }
}

РЕДАКТИРОВАТЬ Это должно предоставить некоторую информацию о том, как создать свой собственный IComparer на основе моего интерфейса выше. Преимущество наличия собственного IComparer на основе интерфейса состоит в том, что вы можете сортировать некоторые столбцы одним способом, а другие столбцами - другим (некоторые столбцы могут быть строками, а некоторые целыми, у некоторых могут быть специальные правила о том, что идет сверху, и т.д.) . Вот пример того, как ваш IComparer может работать:

public class MyGenericComparer : IByColumnComparer
{
  private string columnToCompare;
  private bool descending;

  public string SortColumn
  {
     get { return columnToCompare; }
     set { columnToCompare = value; }
  }

  public bool SortDescending
  {
     get { return descending; }
     set { descending = value; }
  }

  public MyGenericComparer(string column, bool descend)
  {
     columnToCompare = column;
     descending = descend;
  }

  public int Compare(object x, object y)
  {
     MyGenericObject firstObj = (MyGenericObject )x;
     MyGenericObject secondObj = (MyGenericObject )y;

     if (descending) 
     {
        MyGenericObject tmp = secondObj ;
        secondObj = firstObj ;
        firstObj = tmp;
     }

     if (columnToCompare == "StringColumn")
     {
        //Run code to compare strings, return the appropriate int
        //eg, "1" if firstObj was greater, "-1" is secondObj, "0" if equal
     }

     if (columnToCompare == "IntColumn")
     {
        //Run code to compare ints, return the appropriate int
        //eg, "1" if firstObj was greater, "-1" is secondObj, "0" if equal
     }
  }
}

Тогда все, что вам нужно сделать, это создать свой список с экземпляром вашего компаратора!

public static MyGenericComparer GridComparer = new MyGenericComparer();
public static SortableGenericCollection<GenericObject> GridList = new SortableGenericCollection<GenericObject>(GridComparer);
1 голос
/ 03 июня 2011

Возможно, стоит взглянуть на этот вопрос: Сортировка DataGridView и, например, BindingList в .NET

Основная идея заключается в том, что вам нужно расширить BindingList<T> и переопределитьApplySortCore для работы сортировки столбцов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...