Saya memiliki kelas berikut:
[DataContract]
public class Pair<TKey, TValue> : INotifyPropertyChanged, IDisposable
{
public Pair(TKey key, TValue value)
{
Key = key;
Value = value;
}
#region Properties
[DataMember]
public TKey Key
{
get
{ return m_key; }
set
{
m_key = value;
OnPropertyChanged("Key");
}
}
[DataMember]
public TValue Value
{
get { return m_value; }
set
{
m_value = value;
OnPropertyChanged("Value");
}
}
#endregion
#region Fields
private TKey m_key;
private TValue m_value;
#endregion
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
#endregion
#region IDisposable Members
public void Dispose()
{ }
#endregion
}
Yang saya masukkan ke dalam ObservableCollection:
ObservableCollection<Pair<ushort, string>> my_collection =
new ObservableCollection<Pair<ushort, string>>();
my_collection.Add(new Pair(7, "aaa"));
my_collection.Add(new Pair(3, "xey"));
my_collection.Add(new Pair(6, "fty"));
T: Bagaimana cara mengurutkan berdasarkan kunci?
Jawaban:
Mengurutkan yang dapat diamati dan mengembalikan objek yang sama yang diurutkan dapat dilakukan dengan menggunakan metode ekstensi. Untuk koleksi yang lebih besar hati-hati terhadap jumlah koleksi yang berubah pemberitahuan.
Saya telah memperbarui kode saya untuk meningkatkan kinerja dan menangani duplikat (terima kasih kepada nawfal karena menyoroti kinerja yang buruk dari aslinya meskipun itu bekerja dengan baik pada contoh data asli). Observable dipartisi menjadi setengah yang diurutkan kiri dan setengah kanan yang tidak diurutkan, di mana setiap kali item minimum (seperti yang ditemukan dalam daftar yang diurutkan) digeser ke akhir partisi yang diurutkan dari yang tidak diurutkan. Kasus terburuk O (n). Pada dasarnya semacam seleksi (Lihat di bawah untuk keluaran).
penggunaan: Sampel dengan pengamat (menggunakan kelas Person agar tetap sederhana)
Detail kemajuan pengurutan yang menunjukkan bagaimana koleksi diputar:
Kelas Person mengimplementasikan IComparable dan IEquatable yang terakhir digunakan untuk meminimalkan perubahan pada koleksi sehingga dapat mengurangi jumlah pemberitahuan perubahan yang dimunculkan
Untuk mengembalikan ObservableCollection, panggil .ToObservableCollection di * sortOC * menggunakan eg [implementasi ini] [1].
**** orig jawaban - ini membuat koleksi baru **** Anda dapat menggunakan linq seperti yang diilustrasikan oleh metode doSort di bawah ini. Cuplikan kode cepat: menghasilkan
3: xey 6: fty 7: aaa
Alternatifnya, Anda dapat menggunakan metode ekstensi pada koleksi itu sendiri
sumber
ObservableCollection
, melainkan menciptakan koleksi baru.BinarySearch
alih-alihIndexOf
.Ekstensi sederhana ini bekerja dengan baik untuk saya. Saya hanya harus memastikan
MyObject
ituIComparable
. Ketika metode pengurutan dipanggil pada koleksi yang dapat diamatiMyObjects
,CompareTo
metode padaMyObject
dipanggil, yang memanggil metode Urutkan Logis saya. Meskipun tidak semua lonceng dan peluit dari sisa jawaban yang diposting di sini, itulah yang saya butuhkan.sumber
return Utils.LogicalStringCompare(a.Title, b.Title);
bukanreturn string.Compare(a.Title, b.Title);
? @NeilWSaya menemukan entri blog relevan yang memberikan jawaban lebih baik daripada yang ada di sini:
http://kiwigis.blogspot.com/2010/03/how-to-sort-obversablecollection.html
MEMPERBARUI
The ObservableSortedList yang @romkyns poin di komentar secara otomatis menjaga urutan.
Namun perhatikan juga ucapan tersebut
sumber
Anda dapat menggunakan metode sederhana ini:
Anda bisa mengurutkan seperti ini:
Detail lebih lanjut: http://jaider.net/2011-05-04/sort-a-observablecollection/
sumber
ObservableCollection
terikat ke ItemSource dari dropdown dan Anda tidak melihat koleksinya sama sekali. Juga operasi pembersihan dan pengisian ini sangat cepat ... yang "lambat" bisa jadi jenis yang sudah dioptimalkan. akhirnya, Anda dapat memodifikasi kode ini untuk mengimplementasikan metode pemindahan Anda, memilikisortedlist
dansource
sisanya mudah.Move
peristiwa, itu juga hanya untuk yang benar-benar terharu.WPF menyediakan penyortiran langsung di luar kotak menggunakan
ListCollectionView
kelas ...Setelah inisialisasi ini selesai, tidak ada lagi yang harus dilakukan. Keuntungan dari jenis pasif adalah ListCollectionView melakukan semua pekerjaan berat dengan cara yang transparan bagi pengembang. Item baru secara otomatis ditempatkan dalam urutan yang benar. Setiap kelas yang diturunkan dari
IComparer
T cocok untuk properti sortir kustom.Lihat ListCollectionView untuk dokumentasi dan fitur lainnya.
sumber
Saya menyukai pendekatan metode ekstensi semacam gelembung pada blog "Richie" di atas, tetapi saya tidak ingin hanya mengurutkan membandingkan seluruh objek. Saya lebih sering ingin menyortir properti tertentu dari objek. Jadi saya memodifikasinya untuk menerima pemilih kunci seperti yang dilakukan OrderBy sehingga Anda dapat memilih properti mana yang akan disortir:
Yang akan Anda panggil dengan cara yang sama seperti Anda memanggil OrderBy kecuali itu akan mengurutkan instance yang ada dari ObservableCollection Anda alih-alih mengembalikan koleksi baru:
sumber
OrderBy
dan kemudian melakukan perbandingan untuk mengetahui perubahan aktual.@NielW Jawabannya adalah cara untuk pergi, untuk penyortiran di tempat yang nyata. Saya ingin menambahkan solusi yang sedikit diubah yang memungkinkan Anda melewati keharusan menggunakan
IComparable
:sekarang Anda dapat menyebutnya seperti kebanyakan metode LINQ lainnya:
sumber
if(!Ascending) sorted.Reverse();
tepat sebelumfor
: D (dan tidak perlu -lebih jauh- khawatir tentang memori, metode Reverse itu tidak membuat objek baru, metode ini sebaliknya)Saya ingin menambahkan jawaban NeilW . Untuk memasukkan metode yang menyerupai orderby. Tambahkan metode ini sebagai ekstensi:
Dan gunakan seperti:
sumber
Variasi adalah tempat Anda mengurutkan koleksi menggunakan algoritme pengurutan pilihan . Elemen dipindahkan ke tempatnya menggunakan
Move
metode ini. Setiap gerakan akan mengaktifkanCollectionChanged
acara denganNotifyCollectionChangedAction.Move
(dan jugaPropertyChanged
dengan nama propertiItem[]
).Algoritme ini memiliki beberapa properti bagus:
CollectionChanged
peristiwa yang diaktifkan) hampir selalu lebih sedikit daripada algoritme serupa lainnya seperti jenis penyisipan dan jenis gelembung.Algoritmanya cukup sederhana. Koleksi diulang untuk menemukan elemen terkecil yang kemudian dipindahkan ke awal koleksi. Proses ini diulangi mulai dari elemen kedua dan seterusnya sampai semua elemen dipindahkan ke tempatnya. Algoritme ini tidak terlalu efisien tetapi untuk apa pun yang akan Anda tampilkan di antarmuka pengguna, hal itu seharusnya tidak menjadi masalah. Namun, dari segi jumlah operasi pemindahan cukup efisien.
Berikut adalah metode ekstensi yang untuk kesederhanaan memerlukan implementasi elemen
IComparable<T>
. Pilihan lain menggunakanIComparer<T>
atau aFunc<T, T, Int32>
.Menyortir koleksi hanyalah masalah menjalankan metode ekstensi:
sumber
T
untuk dapat mengurutkan elemen-elemen dalam koleksi. Pengurutan melibatkan konsep lebih besar dan lebih kecil dari dan hanya Anda yang dapat menentukan cara pengurutanProfileObject
. Untuk menggunakan metode ekstensi Anda perlu untuk mengimplementasikanIComparable<ProfileObject>
padaProfileObject
. Alternatif lain adalah seperti yang dicatat dengan menentukanIComparer<ProfileObject>
atau aFunc<ProfileObject, ProfileObject, int>
dan mengubah kode pengurutan yang sesuai.Untuk meningkatkan sedikit metode ekstensi pada jawaban xr280xr saya menambahkan parameter bool opsional untuk menentukan apakah pengurutan menurun atau tidak. Saya juga memasukkan saran yang dibuat oleh Carlos P dalam komentar untuk jawaban itu. Silahkan lihat di bawah ini.
sumber
Apakah Anda perlu menyortir koleksi Anda setiap saat? Saat mengambil pasangan, apakah Anda membutuhkannya untuk selalu disortir, atau hanya untuk beberapa kali (mungkin hanya untuk presentasi)? Berapa besar koleksi yang Anda harapkan? Ada banyak faktor yang dapat membantu Anda memutuskan metode penyihir yang akan digunakan.
Jika Anda memerlukan koleksi untuk disortir setiap saat, bahkan ketika Anda memasukkan atau menghapus elemen dan kecepatan penyisipan tidak menjadi masalah, mungkin Anda harus menerapkan beberapa jenis
SortedObservableCollection
seperti yang disebutkan @Gerrie Schenck atau lihat penerapan ini .Jika Anda ingin koleksi Anda disortir hanya untuk beberapa kali gunakan:
Ini akan membutuhkan waktu untuk menyortir koleksi, tetapi meskipun demikian, ini mungkin solusi terbaik tergantung pada apa yang Anda lakukan dengannya.
sumber
Jawaban saya saat ini sudah mendapatkan suara terbanyak, tetapi saya menemukan cara yang lebih baik dan lebih modern untuk melakukan ini.
sumber
Buat kelas baru
SortedObservableCollection
, dapatkan dariObservableCollection
dan implementasikanIComparable<Pair<ushort, string>>
.sumber
Salah satu caranya adalah dengan mengubahnya menjadi List dan kemudian memanggil Sort (), memberikan delegasi perbandingan. Sesuatu seperti:-
(belum dicoba)
sumber
Menurut saya ini adalah solusi paling elegan:
http://www.xamlplayground.org/post/2009/07/18/Use-CollectionViewSource-effectively-in-MVVM-applications.aspx
sumber
Apa-apaan, saya akan memberikan jawaban yang dibuat dengan cepat juga ... sepertinya beberapa implementasi lain di sini, tetapi saya akan menambahkannya siapa saja:
(hampir tidak diuji, semoga saya tidak mempermalukan diri sendiri)
Mari nyatakan beberapa tujuan terlebih dahulu (asumsi saya):
1) Harus menyortir
ObservableCollection<T>
di tempat, untuk mempertahankan pemberitahuan, dll.2) Tidak boleh sangat tidak efisien (yaitu, sesuatu yang mendekati efisiensi penyortiran "baik" standar)
sumber
Tak satu pun dari jawaban ini berhasil dalam kasus saya. Entah karena itu mengacaukan pengikatan, atau membutuhkan begitu banyak pengkodean tambahan sehingga itu semacam mimpi buruk, atau jawabannya hanya rusak. Jadi, inilah jawaban sederhana lainnya yang saya pikir. Ini adalah kode yang jauh lebih sedikit dan tetap menjadi koleksi yang dapat diamati yang sama dengan tambahan metode this.sort. Beri tahu saya jika ada alasan mengapa saya tidak boleh melakukannya dengan cara ini (efisiensi, dll.)?
... Dimana ScoutItem adalah kelas umum saya. Sepertinya jauh lebih sederhana. Manfaat tambahan: ini benar-benar berfungsi dan tidak mengacaukan binding atau mengembalikan koleksi baru, dll.
sumber
Baiklah, karena saya mengalami masalah dalam mendapatkan ObservableSortedList untuk bekerja dengan XAML, saya melanjutkan dan membuat SortingObservableCollection . Ini mewarisi dari ObservableCollection, sehingga bekerja dengan XAML dan saya telah mengujinya ke 98% cakupan kode. Saya telah menggunakannya di aplikasi saya sendiri, tetapi saya tidak akan menjanjikan bahwa ini bebas bug. Jangan ragu untuk berkontribusi. Berikut adalah contoh penggunaan kode:
Ini adalah PCL, jadi harus bekerja dengan Windows Store, Windows Phone, dan .NET 4.5.1.
sumber
new
semua metode tersebut, jika seseorang memiliki instans yang lebih umum diketik, metode tersebut tidak akan dipanggil. Alihoverride
- alih, setiap metode yang dapat diganti dan ubah sesuai kebutuhan atau lakukan fallbackbase.Method(...)
. Anda misalnya bahkan tidak perlu khawatir.Add
karena itu menggunakan internal.InsertItem
, jadi jika.InsertItem
diganti dan disesuaikan,.Add
tidak akan main-main dengan pemesanan.Inilah yang saya lakukan dengan ekstensi OC:
sumber
Ini berhasil untuk saya, sudah lama ditemukan di suatu tempat.
Pemakaian:
sumber
Saya harus dapat mengurutkan berdasarkan banyak hal, bukan hanya satu. Jawaban ini didasarkan pada beberapa jawaban lain tetapi memungkinkan pengurutan yang lebih rumit.
Saat Anda menggunakannya, teruskan serangkaian panggilan OrderBy / ThenBy. Seperti ini:
sumber
Saya belajar banyak dari solusi lain, tetapi saya menemukan beberapa masalah. Pertama, beberapa bergantung pada IndexOf yang cenderung sangat lambat untuk daftar besar. Kedua, ObservableCollection saya memiliki entitas EF dan menggunakan Hapus tampaknya merusak beberapa properti kunci asing. Mungkin aku melakukan sesuatu yang salah.
Terlepas dari itu, A Move dapat digunakan sebagai gantinya Hapus / Sisipkan, tetapi itu menyebabkan beberapa masalah dengan perbaikan kinerja.
Untuk memperbaiki masalah kinerja, saya membuat kamus dengan nilai yang diurutkan IndexOf. Untuk menjaga kamus tetap mutakhir dan untuk mempertahankan properti entitas, gunakan swap yang diimplementasikan dengan dua gerakan, bukan satu seperti yang diterapkan di solusi lain.
Satu gerakan menggeser indeks elemen antara lokasi, yang akan membatalkan kamus IndexOf. Menambahkan langkah kedua untuk mengimplementasikan swap memulihkan lokasi.
sumber
sumber