2014-01-26 110 views
2

這裏GrdView是一個DataGridView。 和 'obj.Code' 是字母數字型的(如R12,BA3,BA21 ...)如何根據列內容對DataGridView進行排序?

private SortableBindingList<myClass> objList = new SortableBindingList<myClass>(); 

DataTable table = new DataTable(); 
table.Columns.Add("code", typeof(string)); 

foreach (var obj in objList) 
{ 
    table.Rows.Add(obj.Code); 
} 

GrdView.DataSource = table; 

這通過點擊列標題排序DataGridView的,但排序是字母數字。 我想排序DataGridView的列只有其數字內容(不是領先的字母)。

+0

在解決問題時,您應該接受答案。 – pid

回答

1

您需要創建另一列進行排序(您可以將其設置爲Visible property = false)。將所有這些代碼粘貼到一個新的窗體窗體中,它將按照您所描述的方式工作(刪除FormX.designer.cs文件)。 SortableCode列使用正則表達式來刪除前導字母字符。

using System; 
using System.Collections; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Linq; 
using System.Reflection; 
using System.Text.RegularExpressions; 
using System.Windows.Forms; 

namespace StackOverflowQuestion21361045 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     public class myClass 
     { 
      public string Code { get; set; } 

      public string SortableCode 
      { 
       get 
       { 
        return Regex.Replace(Code, @"^[^\d]+", string.Empty); 
       } 
      } 
     } 

     private readonly SortableBindingList<myClass> objList = new SortableBindingList<myClass>(); 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      objList.Add(new myClass {Code = "A23"}); 
      objList.Add(new myClass {Code = "B12"}); 
      objList.Add(new myClass {Code = "C04" }); 
      dataGridView1.DataSource = objList; 
      dataGridView1.Sort(dataGridView1.Columns[1], ListSortDirection.Ascending); 
     } 

     private void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) 
     { 
      DataGridViewColumn newColumn = dataGridView1.Columns[e.ColumnIndex]; 
      DataGridViewColumn previouslySortedColumn = dataGridView1.SortedColumn; 
      ListSortDirection direction; 

      if (newColumn == dataGridView1.Columns[0]) 
       newColumn = dataGridView1.Columns[1]; //if the user sorts by code, change the column so as to sort by SortableCode 
      // If oldColumn is null, then the DataGridView is not sorted. 
      if (previouslySortedColumn != null) 
      { 
       // Sort the same column again, reversing the SortOrder. 
       if (previouslySortedColumn == newColumn && 
        dataGridView1.SortOrder == SortOrder.Ascending) 
       { 
        direction = ListSortDirection.Descending; 
       } 
       else 
       { 
        // Sort a new column and remove the old SortGlyph. 
        direction = ListSortDirection.Ascending; 
        previouslySortedColumn.HeaderCell.SortGlyphDirection = SortOrder.None; 
       } 
      } 
      else 
      { 
       direction = ListSortDirection.Ascending; 
      } 

      // Sort the selected column. 
      dataGridView1.Sort(newColumn, direction); 
      newColumn.HeaderCell.SortGlyphDirection = 
       direction == ListSortDirection.Ascending ? 
       SortOrder.Ascending : SortOrder.Descending; 
     } 

     private void dataGridView1_DataBindingComplete(object sender, 
      DataGridViewBindingCompleteEventArgs e) 
     { 
      // Put each of the columns into programmatic sort mode. 
      foreach (DataGridViewColumn column in dataGridView1.Columns) 
      { 
       column.SortMode = DataGridViewColumnSortMode.Programmatic; 
      } 
     } 

     /// <summary> 
     /// Required designer variable. 
     /// </summary> 
     private System.ComponentModel.IContainer components = null; 

     /// <summary> 
     /// Clean up any resources being used. 
     /// </summary> 
     /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> 
     protected override void Dispose(bool disposing) 
     { 
      if (disposing && (components != null)) 
      { 
       components.Dispose(); 
      } 
      base.Dispose(disposing); 
     } 

     #region Windows Form Designer generated code 

     /// <summary> 
     /// Required method for Designer support - do not modify 
     /// the contents of this method with the code editor. 
     /// </summary> 
     private void InitializeComponent() 
     { 
      this.dataGridView1 = new System.Windows.Forms.DataGridView(); 
      ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit(); 
      this.SuspendLayout(); 
      // 
      // dataGridView1 
      // 
      this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; 
      this.dataGridView1.Dock = System.Windows.Forms.DockStyle.Fill; 
      this.dataGridView1.Location = new System.Drawing.Point(0, 0); 
      this.dataGridView1.Name = "dataGridView1"; 
      this.dataGridView1.Size = new System.Drawing.Size(284, 261); 
      this.dataGridView1.TabIndex = 0; 
      this.dataGridView1.ColumnHeaderMouseClick += new System.Windows.Forms.DataGridViewCellMouseEventHandler(this.dataGridView1_ColumnHeaderMouseClick); 
      this.dataGridView1.DataBindingComplete += new System.Windows.Forms.DataGridViewBindingCompleteEventHandler(this.dataGridView1_DataBindingComplete); 
      // 
      // Form1 
      // 
      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 
      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 
      this.ClientSize = new System.Drawing.Size(284, 261); 
      this.Controls.Add(this.dataGridView1); 
      this.Name = "Form1"; 
      this.Text = "Form1"; 
      this.Load += new System.EventHandler(this.Form1_Load); 
      ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit(); 
      this.ResumeLayout(false); 

     } 

     #endregion 

     private System.Windows.Forms.DataGridView dataGridView1; 

     public class SortableBindingList<T> : BindingList<T> 
     { 
      private ArrayList sortedList; 
      private ArrayList unsortedItems; 
      private bool isSortedValue; 

      public SortableBindingList() 
      { 
      } 

      public SortableBindingList(IList<T> list) 
      { 
       foreach (object o in list) 
       { 
        this.Add((T)o); 
       } 
      } 

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

      protected override int FindCore(PropertyDescriptor prop, object key) 
      { 
       PropertyInfo propInfo = typeof(T).GetProperty(prop.Name); 
       T item; 

       if (key != null) 
       { 
        for (int i = 0; i < Count; ++i) 
        { 
         item = (T)Items[i]; 
         if (propInfo.GetValue(item, null).Equals(key)) 
          return i; 
        } 
       } 
       return -1; 
      } 

      public int Find(string property, object key) 
      { 
       PropertyDescriptorCollection properties = 
        TypeDescriptor.GetProperties(typeof(T)); 
       PropertyDescriptor prop = properties.Find(property, true); 

       if (prop == null) 
        return -1; 
       else 
        return FindCore(prop, key); 
      } 

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


      protected override bool IsSortedCore 
      { 
       get { return isSortedValue; } 
      } 

      ListSortDirection sortDirectionValue; 
      PropertyDescriptor sortPropertyValue; 

      protected override void ApplySortCore(PropertyDescriptor prop, 
       ListSortDirection direction) 
      { 
       sortedList = new ArrayList(); 

       Type interfaceType = prop.PropertyType.GetInterface("IComparable"); 

       if (interfaceType == null && prop.PropertyType.IsValueType) 
       { 
        Type underlyingType = Nullable.GetUnderlyingType(prop.PropertyType); 

        if (underlyingType != null) 
        { 
         interfaceType = underlyingType.GetInterface("IComparable"); 
        } 
       } 

       if (interfaceType != null) 
       { 
        sortPropertyValue = prop; 
        sortDirectionValue = direction; 

        IEnumerable<T> query = base.Items; 
        if (direction == ListSortDirection.Ascending) 
        { 
         query = query.OrderBy(i => prop.GetValue(i)); 
        } 
        else 
        { 
         query = query.OrderByDescending(i => prop.GetValue(i)); 
        } 
        int newIndex = 0; 
        foreach (object item in query) 
        { 
         this.Items[newIndex] = (T)item; 
         newIndex++; 
        } 
        isSortedValue = true; 
        this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1)); 

       } 
       else 
       { 
        throw new NotSupportedException("Cannot sort by " + prop.Name + 
         ". This" + prop.PropertyType.ToString() + 
         " does not implement IComparable"); 
       } 
      } 

      protected override void RemoveSortCore() 
      { 
       int position; 
       object temp; 

       if (unsortedItems != null) 
       { 
        for (int i = 0; i < unsortedItems.Count;) 
        { 
         position = this.Find("LastName", 
          unsortedItems[i].GetType(). 
          GetProperty("LastName").GetValue(unsortedItems[i], null)); 
         if (position > 0 && position != i) 
         { 
          temp = this[i]; 
          this[i] = this[position]; 
          this[position] = (T)temp; 
          i++; 
         } 
         else if (position == i) 
          i++; 
         else 
          unsortedItems.RemoveAt(i); 
        } 
        isSortedValue = false; 
        OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1)); 
       } 
      } 

      public void RemoveSort() 
      { 
       RemoveSortCore(); 
      } 
      protected override PropertyDescriptor SortPropertyCore 
      { 
       get { return sortPropertyValue; } 
      } 

      protected override ListSortDirection SortDirectionCore 
      { 
       get { return sortDirectionValue; } 
      } 

     } 
    } 
} 
+1

謝謝,約翰C.我通過修改我的SortableBindingList類與您的代碼示例幫助解決了問題。 –

1

最簡單的方法是添加另一列只包含數字。 您不能根據單元的子部分對數組進行真正的排序。

排序將不得不做很多比較(至少n * ln(n)),因此每個訪問轉換字符串不是一個好的做法。

你應該做的只是將列轉換爲其等價的數字形式,然後按該列進行排序。

排序後,您可以刪除該列,然後將其全部傳遞到HTML中。

1

兩個選擇 -

  1. 可以趕上SortCompare事件並修改其行爲,以滿足您的需求。看看第二個例子在這裏 - http://msdn.microsoft.com/en-us/library/ms171608(v=vs.90).aspx

  2. 可以趕上ColumnHeaderMouseClick Event,然後用適合您的需要

如PID說,在他回答的IComparer手動運行Sort,給予大量在執行比較邏輯時,性能是需要考慮的因素。但是我會首先在大量數據上進行測試,以確保在實施複雜解決方案之前存在問題。

相關問題