Разверните Wpf Treeview для поддержки сортировки - PullRequest
3 голосов
/ 30 марта 2011

Привет! Я создал этот небольшой пример и хотел бы расширить его для поддержки сортировки.

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

Мой xaml:

<TreeView Name="CountryTreeView" ItemsSource="{Binding}">
  <TreeView.ItemTemplate>
    <DataTemplate>
      <TextBlock Text="{Binding Path=Name}"/>
    </DataTemplate>
  </TreeView.ItemTemplate>
</TreeView>

И выделенный код:

readonly ObservableCollection<Country> Countries;

public MainWindow()
{
   InitializeComponent();

   Countries = new ObservableCollection<Country>
   {
       new Country{Name = "Denmark", SortOrder = 0},
       new Country{Name = "Norway", SortOrder = 1},
       new Country{Name = "Sweden", SortOrder = 2},
       new Country{Name = "Iceland", SortOrder = 3},
       new Country{Name = "Greenland", SortOrder = 4},
   };

   CountryTreeView.DataContext = Countries;
}

Я бы хотел, чтобы Treeview Сортировал Countries в зависимости от значения SortOrder.

Он должен быть в состоянии сделать это на лету,Так что, если я, например, поменяю SortOrder = 10 на Name = "Denmark", TreeView автоматически отразит это.

Ответы [ 3 ]

7 голосов
/ 30 марта 2011

Я не думаю, что есть сортировка по умолчанию для TreeViews.Вы можете либо отсортировать элементы перед вводом их в коллекцию, либо перезаписать ObservableCollection, чтобы включить метод Sort.

Я перезаписываю его в одном из моих проектов:

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
}

Затем вы сортируете его, называя что-то вроде

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

Мне нравится перезаписывать его, потому что это позволяет мнедобавьте к нему дополнительные функции, такие как IndexOf или AddRange / RemoveRange

1 голос
/ 30 марта 2011

Вы также можете использовать CollectionViewSource.GetDefaultView с ListCollectionView, чтобы выполнить сортировку для вас, хотя вы должны установить ее и для всех дочерних коллекций. Я использую запрос linq, чтобы сгладить свой список, чтобы найти всех потомков и установить сортировку.

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 );
    }
}

в других местах

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 голосов
/ 08 апреля 2011

Я разработал библиотеку View Model, которая выполняет ряд функций, в том числе позволяет отображать иерархические данные в отсортированном порядке.Библиотека описана в этой статье .Эта часть не включает пример сортировки, но вы можете легко изменить модель представления Demo 2 для сортировки ее иерархических данных.Просто сделайте следующее:

  1. Первый из трех логических аргументов, переданных в базовый конструктор SampleTreeNodePM, указывает, должны ли коллекции View Model использовать те же индексы, что и коллекции Domain Model, или нет.Измените это значение на false.
  2. Последний аргумент возвращаемого значения переопределения метода DesiredPosition является логическим значением, которое указывает, следует ли сортировать коллекцию View Model или нет.Измените это значение на true.
  3. Следуя предыдущему шагу, вам теперь нужно изменить объект модели домена, SampleTreeNode, для реализации IComparable<SampleTreeNode>.Метод CompareTo должен просто делегировать работу строковому свойству Name:

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

Что касается обновления позиции "на лету", как говорит ваш вопрос, просто позвоните мнеметод библиотеки HierarchicalPresentationModel.UpdatePosition после внесения изменений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...