2012-03-11 64 views

回答

0

使用一個專門收集,就像這樣:

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&lt;T, TKey&gt;"/> 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&lt;T, TKey&gt;"/> 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&lt;T, TKey&gt;"/> class. 
     /// </summary> 
     public LongListItem() 
     { 
     } 

     /// <summary> 
     /// Initializes a new instance of the <see cref="LongListItem&lt;T, TKey&gt;"/> 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); 
     } 
    } 
} 
+0

謝謝克勞斯,這工作!只需要跟進兩個問題來提高我的理解:(1)這個「契約」在哪裏擁有一個定義了Key和HasKey屬性的對象集合?換句話說,我如何知道這是預期的?(2)有沒有一種方法可以使用Expression Blend的xml namesapce(即d:DataContext)使用設計時數據上下文來實現相同的功能? – 2012-03-11 18:31:40

+0

Silverlight工具包中的例子會告訴你,但通常它是一個key => value(值是一個集合)映射,其中'GroupItemTemplate'綁定到'Key'屬性。 – 2012-03-11 19:12:12

+0

這些鏈接只是404。解決方案是什麼? – 2012-09-28 00:40:27

0
+0

請注意,您應該在此處發佈答案的有用觀點,或將您的帖子風險刪除爲[「未回答」](http://meta.stackexchange.com/q/8259)。如果您願意,您可能仍然包含鏈接,但僅作爲「參考」。答案應該獨立,不需要鏈接。 – 2013-02-04 20:22:55

+0

此外,它只適用於Windows Phone 8 – Brendan 2013-05-11 10:49:50

+0

這是真的鏈接是Wp8,但該方法也適用於wp7。實際上,如果用簡單的字符列表替換SortedLocalGrouping,則甚至可以使用Alpha Key類 – pkr2000 2013-07-31 21:33:32