如何在排序的 silverlight 树视图中维护当前选择?

发布于 2024-10-06 10:28:50 字数 4641 浏览 0 评论 0原文

我有一个带有数据层次结构的 silverlight 4 TreeView 控件。我希望每个级别中的项目按字母顺序排序,因此我使用 CollectionViewSource,但实际上并不关心排序是如何完成的。

CollectionViewSource 似乎观察 CollectionChanged 事件,因此在添加和删除项目时排序工作正常。

CollectionViewSource 不会观察排序所依据的属性的更改,因此当项目的文本更改时,不会维持排序。调用CollectionViewSource.View.Refresh() 会对列表重新排序,但会放弃选择。如何保留 TreeView 选择而不丢失并重新设置选择

示例项目:

描述:

该项目创建单级项目树。每个项目都有一个项目编号和一个数字前缀,以使排序实际上做一些有趣的事情。这些按钮将添加一个项目、删除最旧的项目以及重命名最旧的项目。

构建示例:

  • 创建一个名为“SortTest”的新 silverlight 应用程序
  • 添加对 System.Windows.Controls 的引用(对于树视图)
  • 更新以下文件:

要注意的行为:

  • 添加和删​​除项目时,当前选择将保持不变。
  • 当项目被重命名时(当从 OnRenameButtonClick() 中调用 Refresh() 时),当前选择将丢失。
  • 如果删除对 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); }
        }
    }
}

谢谢!

I have a silverlight 4 TreeView control with a hierarchy of data. I want the items in each level to be sorted alphabetically, so I am using a CollectionViewSource, but don't actually care how the sorting is accomplished.

The CollectionViewSource seems to observe CollectionChanged events, so the sorting works fine as items are added and removed.

The CollectionViewSource does not observe changes to the property being sorted upon, so when the item's text changes, the sorting is not maintained. Calling CollectionViewSource.View.Refresh() re-sorts the list, but discards the selection. How can I keep the TreeView selection without losing and re-setting the selection?

Sample Project:

Description:

This project creates a single-level tree of items. Each item is given an item number, and a numeric prefix to make the sorting actually do something interesting. The buttons will add an item, remove the oldest item, and rename the oldest item.

Building the sample:

  • Create a new silverlight application named "SortTest"
  • Add a reference to System.Windows.Controls (for the treeview)
  • Update the following files:

Behavior to note:

  • The current selection is maintained as items are added and removed.
  • The current selection is lost when an item is renamed (when Refresh() is called from within OnRenameButtonClick()).
  • If the call to Refresh() is removed, the selection is maintained when renaming an item, but the list is not re-sorted to account for the name change.

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

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

野稚 2024-10-13 10:28:50

将所选项目持久保存到isolatedStorage 中,并在重新加载树视图后重新选择它。

persist the selected item into the isolatedStorage and reselect it after your treeview is reloaded.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文