2009-07-31 16 views
6

Bir ListView .net 2.0Bir çeşit tamsayı liste görünümü biçiminde

C#, Winform tamsayılar sütunları sıralayabilirim nasıl nasıl

System.Windows.Forms.ListView

+1

ASP.NET? Windows formları? –

+0

Tam bir örnek eklemek için cevabımı düzenledim, hem metin hem de sayısal –

cevap

19

Birden çok sütunta sıralama yapabilmem ve her bir sütunu bir sayı veya metin olarak sıralayabilmem için bu şekilde çalıştım.

bu sınıf

İlk kullanım:

lvSeries.ListViewItemSorter = new Sorter(); 

Sonra böyle bile senin listview kontrolü ColumnClick işlemek: formunuzun Yapıcıda

class Sorter : System.Collections.IComparer 
{ 
    public int Column = 0; 
    public System.Windows.Forms.SortOrder Order = SortOrder.Ascending; 
    public int Compare(object x, object y) // IComparer Member 
    { 
     if (!(x is ListViewItem)) 
      return (0); 
     if (!(y is ListViewItem)) 
      return (0); 

     ListViewItem l1 = (ListViewItem)x; 
     ListViewItem l2 = (ListViewItem)y; 

     if (l1.ListView.Columns[Column].Tag == null) 
     { 
      l1.ListView.Columns[Column].Tag = "Text"; 
     } 

     if (l1.ListView.Columns[Column].Tag.ToString() == "Numeric") 
     { 
      float fl1 = float.Parse(l1.SubItems[Column].Text); 
      float fl2 = float.Parse(l2.SubItems[Column].Text); 

      if (Order == SortOrder.Ascending) 
      { 
       return fl1.CompareTo(fl2); 
      } 
      else 
      { 
       return fl2.CompareTo(fl1); 
      } 
     } 
     else 
     { 
      string str1 = l1.SubItems[Column].Text; 
      string str2 = l2.SubItems[Column].Text; 

      if (Order == SortOrder.Ascending) 
      { 
       return str1.CompareTo(str2); 
      } 
      else 
      { 
       return str2.CompareTo(str1); 
      } 
     } 
    } 
} 

böyle ayırıcı set

private void lvSeries_ColumnClick(object sender, ColumnClickEventArgs e) 
    { 
     Sorter s = (Sorter)lvSeries.ListViewItemSorter; 
     s.Column = e.Column; 

     if (s.Order == System.Windows.Forms.SortOrder.Ascending) 
     { 
      s.Order = System.Windows.Forms.SortOrder.Descending; 
     } 
     else 
     { 
      s.Order = System.Windows.Forms.SortOrder.Ascending; 
     } 
     lvSeries.Sort(); 
    } 

Bu, her bir sütunun Tag özelliğine bağlıdır. eric "ya da değil, bu yüzden sıralayıcı nasıl sıralanacağını biliyor.

Yukarıdaki örnekte, sayısal olarak değerleri floats olarak yayınlıyorum, bunu int olarak değiştirmek isteyebilirsiniz.

+1

@Neil: Varsayılan olarak bunları metin olarak sıralar. Örneğin. 100 önce 3 gelir. Ancak, int özel olarak özel ListViewItemSorter ile sıralayabilirsiniz. –

+0

Ahh bu doğru. dize varsayılan türüdür. –

+0

http://support.microsoft.com/kb/319401 adresindeki örneği izledim, ancak yine de tamsayıları doğru sıralamıyor. Metni, sıralamak için varsayılan sütunu nasıl ayarlarsınız. Sütun 1'de gayet iyi bir şekilde listeleniyor, ancak sütunun sıralanması için ayarlanacak özelliği bulamıyorum. – Brad

0

ben istiyorum görünüm yerine veri kaynağında (model) yapın. Onu orada sıralayın ve veritabanında görüntüleyerek güncelleyin.

+0

olarak sıralayabiliyorsunuz, örneğimdeki veri kümesini sıralayabiliyorsunuz ve daha sonra bir sütun tıklandığında liste görünümünü yeniden yükleyeceksiniz? – Brad

+0

no, her seferinde yeniden yüklemek için kötü bir uygulama. Google "ListViewItemSorter" ve her bir sütuna göre nasıl sıralanacağını gösterecek. –

+0

evet, düşündüğüm buydu. – Brad

3

IComparer arabirimini (jenerik olmayan) uygulayan bir sınıf oluşturmanız gerekecektir. Bu sınıfta Doğru alt öğeden Text okuma özelliği, bu int dönüştürmek ve karşılaştırma yapın: Sonra

public class IntegerComparer : IComparer 
{ 
    private int _colIndex; 
    public IntegerComparer(int colIndex) 
    { 
     _colIndex = colIndex; 
    } 
    public int Compare(object x, object y) 
    { 
     int nx = int.Parse((x as ListViewItem).SubItems[_colIndex].Text); 
     int ny = int.Parse((y as ListViewItem).SubItems[_colIndex].Text); 
     return nx.CompareTo(ny); 
    } 
} 

Eğer ListViewItemSorter özelliğine böyle bir karşılaştırıcısı atamak ve ListView sıralama yöntemini çağırmak kontrol: Bunun yerine bir ObjectListView kullanırsanız

bir ListView ile başlarken ise
// create a comparer for column index 1 and assign it to the control, and sort 
myListView.ListViewItemSorter = new IntegerComparer(1); 
myListView.Sort(); 
+0

bazı sütunlar sayısal diğer metinlerdir ... sıralamadan önce sayısal olarak test etmeliyim? – Brad

+1

Bir keresinde her bir elemanı inceleyen bir ListViewItem karşılaştırması yaptım Karşılaştırma yönteminde eşleştirin, ancak bu oldukça yavaş oldu: Ayrı karşılaştırıcılara sahip olmaktan ve hangisinin sıralandığını hangi sütuna göre kullanacağını seçmekten veya yapıcıya bir değer iletip geçirmediğinizi belirten bir karşılaştırma sınıfı oluşturmadan daha iyi olursunuz. sayılara, tarihlere veya metinlere göre bir sıralama yapmak ve sonra da bu değere dayanan Karşılaştırma yöntemini değiştirmek (bu durumda benim için gittiğim çözüm) . –

+0

İyi fikir. Ama 'sortType' gibi özel bir değişken oluşturdum. list listemde karşılaştır yerine ss. – Chris

5

, hayatınızı çok daha kolay olacaktır. ObjectListView, .NET WinForms ListView etrafında açık kaynak kodlu bir paketleyicidir ve normalde bir ListView ile çalışmayı çok sinir bozucu hale getiren tüm bu can sıkıcı küçük sorunları çözer. Örneğin, "100" in '3' sonra gelmesi için otomatik olarak sıralar. (DateTimes, bools ve diğer her şey de doğru şekilde sıralanır).

Gerçekten, bir ObjectListView kullandıktan sonra düz bir ListView'a dönmek istemeyeceksiniz.

Evet, yazarım - ama bu önyargılı olduğum anlamına gelmez ... Tamam, belki de belki de :) Diğer insanların düşünceleri için here'a bakın.

+0

Teşekkürler ... Şu anda bir test sürüşü vereceğim – Brad

0

Neil-N'nin sınıfını kullandım, ancak Tag özelliğini yerine Type özelliğini test etmek için if ifadesini değiştirdim. Her sütunu, içinde tamsayı değeri olan Type Number (Text yerine) olarak ayarlıyorum. Sıralama harika çalışıyor.

if (l1.ListView.Columns[Column].Type.ToString() == "Number") 
+0

Bir şey çıkardığınızdan emin değilim ama [ColumnHeader] (http://msdn.microsoft.com/en-us/library/system.windows .forms.columnheader.aspx) 'Type' özelliği yoktur. – Nick

0
class ListViewAutoSorter : System.Collections.IComparer 
{ 
    private int Column = 0; 
    private System.Windows.Forms.SortOrder Order = SortOrder.Ascending; 

    public ListViewAutoSorter(int Column, SortOrder Order) 
    { 
     this.Column = Column; 
     this.Order = Order; 
    } 

    public int Compare(object x, object y) // IComparer Member 
    { 
     if (!(x is ListViewItem)) 
      return (0); 
     if (!(y is ListViewItem)) 
      return (0); 

     var l1 = (ListViewItem)x; 
     var l2 = (ListViewItem)y; 

     var value1 = 0.0; 
     var value2 = 0.0; 

     if (Double.TryParse(l1.SubItems[Column].Text, out value1) && 
      Double.TryParse(l2.SubItems[Column].Text, out value2)) 
     { 
      if (Order == SortOrder.Ascending) 
      { 
       return value1.CompareTo(value2); 
      } 
      else 
      { 
       return value2.CompareTo(value1); 
      } 
     } 
     else 
     { 
      var str1 = l1.SubItems[Column].Text; 
      var str2 = l2.SubItems[Column].Text; 

      if (Order == SortOrder.Ascending) 
      { 
       return str1.CompareTo(str2); 
      } 
      else 
      { 
       return str2.CompareTo(str1); 
      } 
     } 
    } 
}