在Windows Phone 7或Windows Phone 8中使用CollectionView进行LongListSelector分组

我遇到了与下面标签中列出的相同的问题

是否可以将CollectionView与LongListSelector一起使用进行分组?

我使用以下代码将LongListSelector与分组绑定。

CollectionViewSource cv = new CollectionViewSource(); cv.Source = comments; cv.GroupDescriptions.Add(new PropertyGroupDescription("Filter")); listSelector.HideEmptyGroups = true; listSelector.ItemsSource = cv.View.Groups; 

但它没有显示任何东西。 有人可以帮我这个吗?

它不支持ICollectionView设计。 控件期望一个组实现IEnumerable,而CollectionViewGroup则不会。 CollectionViewGroup是所有ICollectionView组的基类。

因此,您必须围绕ICollectionView创建一个包装器,以便为LongListSelector期望或修改LongListSelector源代码的接口提供支持。

这是我快速而又脏的包装器实现:

 namespace PresentationModel { using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.ComponentModel; using System.Linq; using System.Windows.Data; public class GroupViewItem : IList, INotifyCollectionChanged { private readonly CollectionViewGroup group; public GroupViewItem(CollectionViewGroup group) { this.group = group; ((INotifyCollectionChanged)this.group.Items).CollectionChanged += HandleCollectionViewGroupChanged; } private void HandleCollectionViewGroupChanged(object sender, NotifyCollectionChangedEventArgs e) { OnCollectionChanged(e); } public object Name { get { return this.group.Name; } } public int Count { get { return this.group.ItemCount; } } public IEnumerator GetEnumerator() { return this.group.Items.GetEnumerator(); } public event NotifyCollectionChangedEventHandler CollectionChanged; private void OnCollectionChanged(NotifyCollectionChangedEventArgs args) { var collectionChanged = this.CollectionChanged; if (collectionChanged != null) { collectionChanged(this, args); } } int IList.Add(object value) { throw new NotSupportedException(); } void IList.Clear() { throw new NotSupportedException(); } bool IList.Contains(object value) { throw new NotSupportedException(); } int IList.IndexOf(object value) { throw new NotSupportedException(); } void IList.Insert(int index, object value) { throw new NotSupportedException(); } bool IList.IsFixedSize { get { throw new NotSupportedException(); } } bool IList.IsReadOnly { get { throw new NotSupportedException(); } } void IList.Remove(object value) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } object IList.this[int index] { get { throw new NotSupportedException(); } set { throw new NotSupportedException(); } } void ICollection.CopyTo(System.Array array, int index) { throw new NotSupportedException(); } bool ICollection.IsSynchronized { get { throw new NotSupportedException(); } } object ICollection.SyncRoot { get { throw new NotSupportedException(); } } } public class GroupView : IEnumerable, INotifyCollectionChanged { private readonly ICollectionView collectionView; private readonly List items; public GroupView(ICollectionView collectionView) { this.items = new List(); this.collectionView = collectionView; ((INotifyCollectionChanged)this.collectionView.Groups).CollectionChanged += HandleCollectionViewGroupsChanged; ResetGroups(notify: false); } private void HandleCollectionViewGroupsChanged(object sender, NotifyCollectionChangedEventArgs e) { switch (e.Action) { case NotifyCollectionChangedAction.Add: AddGroups(e); break; case NotifyCollectionChangedAction.Remove: RemoveGroups(e); break; case NotifyCollectionChangedAction.Replace: ReplaceGroups(e); break; case NotifyCollectionChangedAction.Reset: ResetGroups(); break; } } private IList AddGroups(NotifyCollectionChangedEventArgs e, bool notify = true) { var newGroups = e.NewItems .Cast() .Select(cvg => new GroupViewItem(cvg)) .ToArray(); this.items.InsertRange(e.NewStartingIndex, newGroups); if (notify) { for (var i = 0; i != newGroups.Length; ++i) { OnCollectionChanged(new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Add, newGroups[i], e.NewStartingIndex + i)); } } return newGroups; } private IList RemoveGroups(NotifyCollectionChangedEventArgs e, bool notify = true) { var oldGroups = this.items.GetRange(e.OldStartingIndex, e.OldItems.Count); this.items.RemoveRange(e.OldStartingIndex, e.OldItems.Count); if (notify) { for (var i = 0; i != oldGroups.Count; ++i) { OnCollectionChanged(new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Remove, oldGroups[i], e.OldStartingIndex + i)); } } return oldGroups; } private void ReplaceGroups(NotifyCollectionChangedEventArgs e) { var oldGroups = RemoveGroups(e, notify: false); var newGroups = AddGroups(e, notify: false); if (oldGroups.Count != newGroups.Count) { OnCollectionChanged(new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Reset)); } else { for (var i = 0; i != newGroups.Count; ++i) { OnCollectionChanged(new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Replace, newGroups[i], oldGroups[i], e.NewStartingIndex + i)); } } } private void ResetGroups(bool notify = true) { this.items.Clear(); this.items.AddRange( this.collectionView.Groups .Cast() .Select(cvg => new GroupViewItem(cvg))); if (notify) { OnCollectionChanged(new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Reset)); } } public event NotifyCollectionChangedEventHandler CollectionChanged; public IEnumerator GetEnumerator() { return this.items.GetEnumerator(); } private void OnCollectionChanged(NotifyCollectionChangedEventArgs args) { var collectionChanged = this.CollectionChanged; if (collectionChanged != null) { collectionChanged(this, args); } } } }