Используйте специализированную коллекцию, например:
using System;
using System.Linq;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Collections.ObjectModel;
namespace Stackoverflow.Collections
{
/// <summary>
/// Represents a specialized collection to integrate with the
/// <see cref="Microsoft.Phone.Controls.LongListSelector"/> control.
/// </summary>
/// <typeparam name="T">The type of the values in the collection.</typeparam>
/// <typeparam name="TKey">The type of the keys in the collection.</typeparam>
public class LongListCollection<T, TKey> : ObservableCollection<LongListItem<T, TKey>>
where T : IComparable<T>
where TKey : IComparable<TKey>
{
/// <summary>
/// The key selector for adding items.
/// </summary>
private Func<T, TKey> keySelector;
/// <summary>
/// Initializes a new instance of the <see cref="LongListCollection<T, TKey>"/> class.
/// </summary>
/// <param name="keySelector">The key selector.</param>
public LongListCollection(Func<T, TKey> keySelector)
{
if (keySelector == null)
throw new ArgumentNullException("keySelector");
this.keySelector = keySelector;
}
/// <summary>
/// Initializes a new instance of the <see cref="LongListCollection<T, TKey>"/> class.
/// </summary>
/// <param name="keySelector">The key selector.</param>
/// <param name="items">A initial collection.</param>
public LongListCollection(Func<T, TKey> keySelector, IEnumerable<T> items)
{
if (keySelector == null)
throw new ArgumentNullException("keySelector");
if (items == null)
throw new ArgumentNullException("items");
this.keySelector = keySelector;
var groups = new Dictionary<TKey, LongListItem<T, TKey>>();
foreach (var item in items.OrderBy(x => x))
{
var key = keySelector(item);
if (groups.ContainsKey(key) == false)
groups.Add(key, new LongListItem<T, TKey>(key));
groups[key].Add(item);
}
foreach (var value in groups.Values)
this.Add(value);
}
/// <summary>
/// Adds the specified item to the collection.
/// </summary>
/// <param name="item">The item.</param>
public void Add(T item)
{
TKey key = keySelector(item);
var group = this.FirstOrDefault(x => x.Key.Equals(key));
if (group != null)
group.Add(item);
else
this.Add(new LongListItem<T, TKey>(key) { item });
}
/// <summary>
/// Inserts an item into the collection at the specified index.
/// </summary>
/// <param name="index">The zero-based index at which item should be inserted.</param>
/// <param name="item">The object to insert.</param>
protected override void InsertItem(int index, LongListItem<T, TKey> item)
{
for (int i = 0; i < this.Count; i++)
{
switch (Math.Sign(this[i].CompareTo(item)))
{
case 0:
throw new InvalidOperationException("Cannot insert duplicated items.");
case 1:
base.InsertItem(i, item);
return;
case -1:
break;
}
}
base.InsertItem(this.Count, item);
}
}
/// <summary>
/// Represents a specialized data structure to integrate with the
/// <see cref="Microsoft.Phone.Controls.LongListSelector"/> control.
/// </summary>
/// <typeparam name="T">The type of the values in the structure.</typeparam>
/// <typeparam name="TKey">The type of the key in the structure.</typeparam>
public class LongListItem<T, TKey> : ObservableCollection<T>, IComparable<LongListItem<T, TKey>>
where T : IComparable<T>
where TKey : IComparable<TKey>
{
/// <summary>
/// Initializes a new instance of the <see cref="LongListItem<T, TKey>"/> class.
/// </summary>
public LongListItem()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="LongListItem<T, TKey>"/> class.
/// </summary>
/// <param name="key">The item's key.</param>
public LongListItem(TKey key)
{
this.Key = key;
}
/// <summary>
/// Gets or sets the item key.
/// </summary>
/// <value>The item key.</value>
public TKey Key
{
get;
set;
}
/// <summary>
/// Gets a value indicating whether this instance has any items.
/// </summary>
/// <value><c>true</c> if this instance has any items; otherwise, <c>false</c>.</value>
public bool HasItems
{
get
{
return Count > 0;
}
}
/// <summary>
/// Inserts an item into the collection at the specified index.
/// </summary>
/// <param name="index">The zero-based index at which item should be inserted.</param>
/// <param name="item">The object to insert.</param>
protected override void InsertItem(int index, T item)
{
for (int i = 0; i < this.Count; i++)
{
switch (Math.Sign(this[i].CompareTo(item)))
{
case 0:
return;
case 1:
base.InsertItem(i, item);
return;
case -1:
break;
}
}
base.InsertItem(this.Count, item);
}
/// <summary>
/// Compares to.
/// </summary>
/// <param name="other">The other.</param>
/// <returns></returns>
public int CompareTo(LongListItem<T, TKey> other)
{
if (other == null)
return 1;
return this.Key.CompareTo(other.Key);
}
}
}