簡體   English   中英

如何在單擊列 header 的 DataGridView 中對 DataBound 列進行排序?

[英]How do I sort a DataBound column in a DataGridView on a column header click?

我相信這應該自動處理。 我將DataGridView綁定到對象數組:

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

綁定網格:

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

當我單擊“名稱”列中的SortMode列時,即使 SortMode 設置為 Automatic,也沒有任何反應。 header 列中也缺少排序字形。

我嘗試綁定到IBindingListIList ,但這不起作用。

我希望有一個簡單、優雅的解決方案,可以在DataGridViewDataGridViewColumn上設置屬性,而不必制作新的 class 來支持排序。 我應該怎么做才能通過單擊 DataBound DataGridView上的 header 來支持對列進行排序?

我創建了一個新的基於 IComparer 的界面,允許您指定列和方向。 我這樣做只是因為我需要我的排序代碼盡可能通用——我有兩個需要像這樣排序的網格,我不想維護兩次代碼。 這是界面,很簡單:

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

顯然,如果您不擔心保持通用性(您可能應該),那么這並不是絕對必要的。 然后,我構建了一個基於 BindingList<> 的新 class。 這使我可以覆蓋排序代碼並逐列提供我自己的 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);

可能想看看這個問題: DataGridView sort and eg BindingList<T> in .NET

基本思想是您必須擴展BindingList<T>並覆蓋ApplySortCore才能使列排序正常工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM