Expand Wpf Treeview to support Sorting

前端 未结 3 1080
深忆病人
深忆病人 2021-01-21 09:48

Hi I created this small example, and I would like to expand it to support Sorting.

public class Country
{
    public string Name { get; set; }
    public int Sor         


        
相关标签:
3条回答
  • 2021-01-21 09:58

    I don't think there is a default sort for TreeViews. You can either sort the items prior to entering them into the collection, or overwrite the ObservableCollection to include a Sort method.

    I overwrite it in one of my projects:

    public class SortableObservableCollection<T> : ObservableCollection<T>
    {
        // Constructors
        public SortableObservableCollection() : base(){}
        public SortableObservableCollection(List<T> l) : base(l){}
        public SortableObservableCollection(IEnumerable<T> l) :base (l) {}
    
        #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 // Sorting
    }
    

    You would then sort it by calling something like

    Countries.Sort(country => country.SortOrder);
    

    I like overwriting it because it let me add additional functionality to it as well such as IndexOf or AddRange/RemoveRange

    0 讨论(0)
  • 2021-01-21 10:00

    I developed a View Model library which does a number of things, including letting you display hierarchical data in sorted order. The library is described in this article. The piece doesn't include a sorting example, but you can easily modify the Demo 2's View Model to sort its hierarchical data. Just do the following:

    1. The first of three boolean arguments passed to SampleTreeNodePM's base constructor indicates if the View Model collections should use the same indices as the Domain Model collections or not. Change this value to false.
    2. The last argument to the DesiredPosition method override's return value is a boolean that indicates whether to sort the View Model collection or not. Change this value to true.
    3. Following from the previous step, you now need to modify the Domain Model object, SampleTreeNode, to implement IComparable<SampleTreeNode>. The CompareTo method need simply delegate the job to the Name string property:

      public int CompareTo( SampleTreeNode other )
      {
          return Name.CompareTo( other.Name );
      }
      

    Regarding updating the position "on the fly" as your question says, just call my library's HierarchicalPresentationModel.UpdatePosition method after making the change.

    0 讨论(0)
  • 2021-01-21 10:11

    You can also use the CollectionViewSource.GetDefaultView with ListCollectionView to do the sorting for you, tho you do have to set it for all the child collections as well. I use a linq query to flatten my list to find all the children and set the sorting.

    foreach (var structure in Model.Structures.Flatten(t => t.SubItems))
    {
        var view = CollectionViewSource
            .GetDefaultView(structure.SubItems) as ListCollectionView;
    
        if (view != null)
        {
            view.CustomSort = (x,y) => string.Compare( x, y );
        }
    }
    

    elsewhere

    public static IEnumerable<T> Flatten<T>(
        this IEnumerable<T> list, Func<T, IEnumerable<T>> subitems)
    {
        foreach (T child in list)
        {
            yield return child;
    
            foreach (T other in Flatten(subitems(child), subitems))
            {
                yield return other;
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题