2011-09-28 39 views
1

我有一个带有Order属性的Page类型的集合,我将TabControl的ItemsSource属性设置为ObservableCollection。当我更改实体 的Order属性时,我需要的是相关的TabItem进入正确的位置。如何排序TabControl中的TabItems

WPF XAML:

<TabControl Grid.Row="1" ItemsSource="{Binding Pages.ListViewModels}" SelectedItem="{Binding Pages.Current}" > 
    <TabControl.ContentTemplate> 
     <DataTemplate> 
      <views:EditPageView /> 
     </DataTemplate> 
    </TabControl.ContentTemplate> 
    <TabControl.ItemTemplate> 
     <DataTemplate>          
      <TextBlock Text="{Binding Header}"/> 
     </DataTemplate> 
    </TabControl.ItemTemplate> 
</TabControl> 

C#代码:

public class QuestionPageSection : INotifyPropertyChanged 
{ 
    public virtual int Id { get; set; } 
    public virtual string Header { get; set; } 
    private int _Order; 
    public virtual int Order 
    { 
     get 
     { 
      return _Order; 
     } 
     set 
     { 
      _Order = value; 
      this.RaisePropertyChanged(() => this.Order , PropertyChanged); 
     } 
    } 
    public event PropertyChangedEventHandler PropertyChanged; 
} 

我想迫使TabControl的基于Order属性的TabItems排序。所以现在我有这些questoins:

  • 有没有办法做到它声明?
  • TabControl是否有一个SortColumn属性?
  • TabItem是否具有TabOrder属性?
  • 是否有任何类型的集合,听其孩子自动排序自己基于孩子的财产?

任何其他的想法都会变成流行的。

回答

1

你只需要梳理你的TabControl势必

我一直讨厌的事实,ObservableCollection没有收集内置Sort方法,所以我通常使用从ObservableCollection

public class ObservableCollectionEx<T> : ObservableCollection<T> 
{ 
    public ObservableCollectionEx() : base() { } 
    public ObservableCollectionEx(List<T> l) : base(l) { } 
    public ObservableCollectionEx(IEnumerable<T> l) : base(l) { } 

    #region IndexOf 

    /// <summary> 
    /// Returns the index of the first object which meets the specified function 
    /// </summary> 
    /// <param name="keySelector">A bool function to compare each Item by</param> 
    /// <returns>The index of the first Item which matches the function</returns> 
    public int IndexOf(Func<T, bool> compareFunction) 
    { 
     return Items.IndexOf(Items.FirstOrDefault(compareFunction)); 
    } 

    #endregion 

    #region Sorting 

    /// <summary> 
    /// Sorts the items of the collection in ascending order according to a key. 
    /// </summary> 
    /// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam> 
    /// <param name="keySelector">A function to extract a key from an item.</param> 
    public void Sort<TKey>(Func<T, TKey> keySelector) 
    { 
     InternalSort(Items.OrderBy(keySelector)); 
    } 

    /// <summary> 
    /// Sorts the items of the collection in descending order according to a key. 
    /// </summary> 
    /// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam> 
    /// <param name="keySelector">A function to extract a key from an item.</param> 
    public void SortDescending<TKey>(Func<T, TKey> keySelector) 
    { 
     InternalSort(Items.OrderByDescending(keySelector)); 
    } 

    /// <summary> 
    /// Sorts the items of the collection in ascending order according to a key. 
    /// </summary> 
    /// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam> 
    /// <param name="keySelector">A function to extract a key from an item.</param> 
    /// <param name="comparer">An <see cref="IComparer{T}"/> to compare keys.</param> 
    public void Sort<TKey>(Func<T, TKey> keySelector, IComparer<TKey> comparer) 
    { 
     InternalSort(Items.OrderBy(keySelector, comparer)); 
    } 

    /// <summary> 
    /// Moves the items of the collection so that their orders are the same as those of the items provided. 
    /// </summary> 
    /// <param name="sortedItems">An <see cref="IEnumerable{T}"/> to provide item orders.</param> 
    private void InternalSort(IEnumerable<T> sortedItems) 
    { 
     var sortedItemsList = sortedItems.ToList(); 

     foreach (var item in sortedItemsList) 
     { 
      Move(IndexOf(item), sortedItemsList.IndexOf(item)); 
     } 
    } 

    #endregion 
} 

继承自己的自定义类,我可以这样使用它:

ListViewModels = GetListViewModels(); 
ListViewModels.Sort(p => p.Order); 
1

通过使用CollectionViewSource,您可以在UI端对ObservableCollection进行排序。下面是用实例链接:http://msdn.microsoft.com/en-us/library/ms742542.aspx

+0

谢谢,我试过使用CollectionViewSource,但它不起作用。它会对列表进行排序,但不会对影响排序的更改做出响应。 – 000

0

谢谢Rachel,你的解决方案给了我线索,但你的解决方案仍然是一个答案,因为每当我更改Order属性时我都可以手动调用Sort方法,但是我想让它自动完成。所以我最终得到了一个动态版本的代码。

基于瑞秋我接触到这个解决方案。

public class ObservableCollectionEx<T> : ObservableCollection<T> 
{ 
    public ObservableCollectionEx() : base() { } 

    public ObservableCollectionEx(List<T> l) : base(l) { } 

    public ObservableCollectionEx(IEnumerable<T> l) : base(l) { } 

    Func<IEnumerable<T>,IEnumerable<T>> sortFunction; 
    Action reset; 

    #region IndexOf 

    /// <summary> 
    /// Returns the index of the first object which meets the specified function 
    /// </summary> 
    /// <param name="keySelector">A bool function to compare each Item by</param> 
    /// <returns>The index of the first Item which matches the function</returns> 
    public int IndexOf(Func<T , bool> compareFunction) 
    { 
     return Items.IndexOf(Items.FirstOrDefault(compareFunction)); 
    } 

    #endregion IndexOf 

    #region Sorting 

    /// <summary> 
    /// Sorts the items of the collection in ascending order according to a key. 
    /// </summary> 
    /// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam> 
    /// <param name="keySelector">A function to extract a key from an item.</param> 
    public void SetSort<TKey>(Func<T , TKey> keySelector) 
    { 
     sortFunction = list => list.OrderBy(keySelector); 
     InternalSort(); 
     reset =() => SetSort(keySelector); 
    } 

    /// <summary> 
    /// Sorts the items of the collection in descending order according to a key. 
    /// </summary> 
    /// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam> 
    /// <param name="keySelector">A function to extract a key from an item.</param> 
    public void SetSortDescending<TKey>(Func<T , TKey> keySelector) 
    { 
     sortFunction = list => list.OrderByDescending(keySelector); 
     InternalSort(); 
     reset =() => SetSortDescending(keySelector); 
    } 

    /// <summary> 
    /// Sorts the items of the collection in ascending order according to a key. 
    /// </summary> 
    /// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam> 
    /// <param name="keySelector">A function to extract a key from an item.</param> 
    /// <param name="comparer">An <see cref="IComparer{T}"/> to compare keys.</param> 
    public void SetSort<TKey>(Func<T , TKey> keySelector , IComparer<TKey> comparer) 
    { 
     sortFunction = list => list.OrderBy(keySelector , comparer); 
     InternalSort(); 
     reset =() => SetSort(keySelector , comparer); 
    } 

    /// <summary> 
    /// Sorts the items of the collection in descending order according to a key. 
    /// </summary> 
    /// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam> 
    /// <param name="keySelector">A function to extract a key from an item.</param> 
    /// <param name="comparer">An <see cref="IComparer{T}"/> to compare keys.</param> 
    public void SetSortDescending<TKey>(Func<T , TKey> keySelector , IComparer<TKey> comparer) 
    { 
     sortFunction = list => list.OrderByDescending(keySelector , comparer); 
     InternalSort(); 
     reset =() => SetSortDescending(keySelector , comparer); 
    } 

    /// <summary> 
    /// Moves the items of the collection so that their orders are the same as those of the items provided. 
    /// </summary> 
    private void InternalSort() 
    { 
     UpdateTracking(null , Items.ToList()); 
    } 

    private void MoveItemToItsLocation(T item) 
    { 
     var sortListCache = sortFunction(Items).ToList(); 
     Move(IndexOf(item) , sortListCache.IndexOf(item)); 
    } 

    #endregion Sorting 

    public void UpdateTracking(IEnumerable<T> oldItems , IEnumerable<T> newItems) 
    { 
     if (sortFunction == null) return; 

     PropertyChangedEventHandler changeTracker = (o , change) => { MoveItemToItsLocation((T)o); }; 
     Action<T> attachChangeTracker = o => o.ExecuteOnCast<INotifyPropertyChanged>(x => x.PropertyChanged += changeTracker); 
     Action<T> detachChangeTracker = o => o.ExecuteOnCast<INotifyPropertyChanged>(x => x.PropertyChanged -= changeTracker); 

     var greeting = new[] { attachChangeTracker , MoveItemToItsLocation }; 
     var farwell = new[] { detachChangeTracker }; 

     oldItems.ForEach(detachChangeTracker); 
     newItems.ForEach(attachChangeTracker , MoveItemToItsLocation); 
    } 

    protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e) 
    { 
     base.OnCollectionChanged(e); 

     switch (e.Action) { 
      case NotifyCollectionChangedAction.Add: 
      case NotifyCollectionChangedAction.Remove: 
      case NotifyCollectionChangedAction.Replace: 
       UpdateTracking(e.OldItems.SafeGet(x => x.Cast<T>()) , e.NewItems.SafeGet(x => x.Cast<T>())); 
       break; 
      case NotifyCollectionChangedAction.Reset: 
       UpdateTracking(Items.ToList() , null); 
       if (reset != null) 
        reset(); 
       break; 
      default: 
       break; 
     } 
    } 
} 

我只是做了一点改变,使其遵循的基本集合中的变化,所以它会之后的任何更改底层集合或底层集合中的任何元素使自己自动排序。

相关问题