2011-09-28 38 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; 
     } 
    } 
} 

我只是做了一點改變,使其遵循的基本集合中的變化,所以它會之後的任何更改底層集合或底層集合中的任何元素使自己自動排序。

相關問題