オブザーバブルを並べ替え、同じオブジェクトを並べ替えて返すには、拡張メソッドを使用します。大きなコレクションの場合は、コレクション変更通知の数に注意してください。
public static void Sort<T>(this ObservableCollection<T> observable) where T : IComparable<T>, IEquatable<T>
{
List<T> sorted = observable.OrderBy(x => x).ToList();
int ptr = 0;
while (ptr < sorted.Count)
{
if (!observable[ptr].Equals(sorted[ptr]))
{
T t = observable[ptr];
observable.RemoveAt(ptr);
observable.Insert(sorted.IndexOf(t), t);
}
else
{
ptr++;
}
}
}
使用法:オブザーバーを使用したサンプル(単純にするためにPersonクラスを使用)
public class Person:IComparable<Person>,IEquatable<Person>
{
public string Name { get; set; }
public int Age { get; set; }
public int CompareTo(Person other)
{
if (this.Age == other.Age) return 0;
return this.Age.CompareTo(other.Age);
}
public override string ToString()
{
return Name + " aged " + Age;
}
public bool Equals(Person other)
{
if (this.Name.Equals(other.Name) && this.Age.Equals(other.Age)) return true;
return false;
}
}
static void Main(string[] args)
{
Console.WriteLine("adding items...");
var observable = new ObservableCollection<Person>()
{
new Person { Name = "Katy", Age = 51 },
new Person { Name = "Jack", Age = 12 },
new Person { Name = "Bob", Age = 13 },
new Person { Name = "John", Age = 14 },
new Person { Name = "Mary", Age = 41 },
new Person { Name = "Jane", Age = 20 },
new Person { Name = "Jim", Age = 39 },
new Person { Name = "Sue", Age = 15 },
new Person { Name = "Kim", Age = 19 }
};
//what do observers see?
observable.CollectionChanged += (o, e) => {
if (e.OldItems != null)
{
foreach (var item in e.OldItems)
{
Console.WriteLine("removed {0} at index {1}", item, e.OldStartingIndex);
}
}
if (e.NewItems != null)
{
foreach (var item in e.NewItems)
{
Console.WriteLine("added {0} at index {1}", item, e.NewStartingIndex);
}
}};
Console.WriteLine("\nsorting items...");
observable.Sort();
};
上からの出力:
51歳のケイティをインデックス0 から削除
51歳のケイティを
削除インデックス8の51歳のケイティを削除インデックス3の
41歳のメアリーを
削除インデックス7の41歳のメアリーを削除インデックス3の
20歳のジェーンを
削除インデックス5の20歳のジェーンを追加インデックス5の20歳のジェーンを削除ジムの39歳を削除インデックス3で
追加された39歳のジムインデックス6で
削除された20歳のジェーンインデックス4で
追加された20歳のジェーンインデックス5で追加されたジェーン
PersonクラスはIComparableとIEquatableの両方を実装します。後者は、コレクションへの変更を最小限に抑え、発生する変更通知の数を減らすために使用されます
- EDIT新しいコピーを作成せずに同じコレクションをソートします*
ObservableCollectionを返すには、たとえば[この実装] [1]を使用して* sortedOC *で.ToObservableCollectionを呼び出します。
****元の回答-これにより新しいコレクションが作成されます****以下のdoSortメソッドが示すようにlinqを使用できます。簡単なコードスニペット:生成
3:xey 6:fty 7:aaa
または、コレクション自体に拡張メソッドを使用することもできます
var sortedOC = _collection.OrderBy(i => i.Key);
private void doSort()
{
ObservableCollection<Pair<ushort, string>> _collection =
new ObservableCollection<Pair<ushort, string>>();
_collection.Add(new Pair<ushort,string>(7,"aaa"));
_collection.Add(new Pair<ushort, string>(3, "xey"));
_collection.Add(new Pair<ushort, string>(6, "fty"));
var sortedOC = from item in _collection
orderby item.Key
select item;
foreach (var i in sortedOC)
{
Debug.WriteLine(i);
}
}
public class Pair<TKey, TValue>
{
private TKey _key;
public TKey Key
{
get { return _key; }
set { _key = value; }
}
private TValue _value;
public TValue Value
{
get { return _value; }
set { _value = value; }
}
public Pair(TKey key, TValue value)
{
_key = key;
_value = value;
}
public override string ToString()
{
return this.Key + ":" + this.Value;
}
}