Как я могу сохранить текущий выбор в отсортированном дереве Silverlight?

У меня есть элемент управления Silverlight 4 TreeView с иерархией данных. Я хочу, чтобы элементы на каждом уровне были отсортированы в алфавитном порядке, поэтому я использую CollectionViewSource, но на самом деле мне все равно, как выполняется сортировка.

Кажется, что CollectionViewSource наблюдает за событиями CollectionChanged, поэтому сортировка работает нормально, когда элементы добавляются и удаляются.

CollectionViewSource не наблюдает изменений в сортируемом свойстве, поэтому при изменении текста элемента сортировка не сохраняется. Вызов CollectionViewSource.View.Refresh() повторно сортирует список, но отбрасывает выбор. Как я могу сохранить выбор TreeView без потери и повторной установки выбора?

Пример проекта:

Описание:

Этот проект создает одноуровневое дерево элементов. Каждому элементу присваивается номер элемента и числовой префикс, чтобы сортировка действительно делала что-то интересное. Кнопки добавляют элемент, удаляют самый старый элемент и переименовывают самый старый элемент.

Создание образца:

  • Создайте новое приложение Silverlight с именем «SortTest».
  • Добавьте ссылку на System.Windows.Controls (для дерева)
  • Обновите следующие файлы:

Поведение, на которое следует обратить внимание:

  • Текущий выбор сохраняется по мере добавления и удаления элементов.
  • Текущий выбор теряется при переименовании элемента (когда Refresh() вызывается из OnRenameButtonClick()).
  • Если вызов Refresh() удален, выбор сохраняется при переименовании элемента, но список не пересортируется для учета изменения имени.

MainPage.xaml

<UserControl x:Class="SortTest.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">

    <UserControl.Resources>
        <Style x:Key="expandedStyle" TargetType="sdk:TreeViewItem">
            <Setter Property="IsExpanded" Value="true" />
        </Style>

        <sdk:HierarchicalDataTemplate x:Key="template">
            <TextBlock Text="{Binding Name}" />
        </sdk:HierarchicalDataTemplate>
    </UserControl.Resources>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <StackPanel Grid.Row="0" Orientation="Horizontal">
            <Button Click="OnAddButtonClick">
                <TextBlock Text="Add an item" />
            </Button>
            <Button Click="OnRemoveButtonClick">
                <TextBlock Text="Remove lowest numbered item" />
            </Button>
            <Button Click="OnRenameButtonClick">
                <TextBlock Text="Rename lowest numbered item" />
            </Button>
        </StackPanel>

        <sdk:TreeView Grid.Row="1" ItemsSource="{Binding Items}" ItemTemplate="{StaticResource template}" />

    </Grid>
</UserControl>

MainPage.xaml.cs

using System.Windows.Controls;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Data;
using System.ComponentModel;
using System;
using System.Collections.Specialized;

namespace SortTest
{
    public partial class MainPage : UserControl
    {
        private ObservableCollection<ItemViewModel> items = new ObservableCollection<ItemViewModel>();
        private CollectionViewSource sortedItems = new CollectionViewSource();
        private int itemNumber = 1;

        public MainPage()
        {
            sortedItems.Source = items;
            sortedItems.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending));

            DataContext = this;
            InitializeComponent();
        }

        public ICollectionView Items { get { return sortedItems.View; } }

        private void OnAddButtonClick(object sender, RoutedEventArgs e)
        {
            ItemViewModel item = new ItemViewModel();
            item.Name = DateTime.Now.Millisecond.ToString("D3") + " Item #" + itemNumber;
            itemNumber++;
            items.Add(item);
        }

        private void OnRemoveButtonClick(object sender, RoutedEventArgs e)
        {
            if (items.Count > 0)
            {
                items.RemoveAt(0);
            }
        }

        private void OnRenameButtonClick(object sender, RoutedEventArgs e)
        {
            if (items.Count > 0)
            {
                items[0].Name = DateTime.Now.Millisecond.ToString("D3") + items[0].Name.Substring(3);
                sortedItems.View.Refresh();
            }
        }
    }

    public class ItemViewModel : DependencyObject
    {
        public static DependencyProperty NameProperty = DependencyProperty.Register("Name", typeof(string), typeof(ItemViewModel), null);
        public string Name
        {
            get { return GetValue(NameProperty) as string; }
            set { SetValue(NameProperty, value); }
        }
    }
}

Спасибо!


person James Barber    schedule 06.12.2010    source источник


Ответы (1)


сохраните выбранный элемент в изолированном хранилище и повторно выберите его после перезагрузки дерева.

person user753503    schedule 19.05.2011