【问题标题】:How can I sort a ListBox using only XAML and no code-behind?如何仅使用 XAML 而没有代码隐藏对 ListBox 进行排序?
【发布时间】:2009-08-14 23:44:43
【问题描述】:

我需要对ListBox 中的字符串进行排序,但它由另一个组件通过DataContext 绑定到视图模型。所以我不能直接在 XAML 中实例化视图模型,就像在 this example 中一样,它使用了 ObjectDataProvider

在我的 XAML 中:

<ListBox ItemsSource="{Binding CollectionOfStrings}" />

在我的视图模型中:

public ObservableCollection<string> CollectionOfStrings
{
    get { return collectionOfStrings; }
}

在另一个组件中:

view.DataContext = new ViewModel();

后面没有代码!那么使用纯粹的 XAML,我将如何对 ListBox 中的项目进行排序?同样,XAML 不拥有视图模型的实例化。

【问题讨论】:

    标签: wpf xaml sorting mvvm listbox


    【解决方案1】:

    使用CollectionViewSource

    <CollectionViewSource x:Key="SortedItems" Source="{Binding CollectionOfStrings}"
        xmlns:scm="clr-namespace:System.ComponentModel;assembly=Win‌​dowsBase">
        <CollectionViewSource.SortDescriptions>
            <scm:SortDescription PropertyName="SomePropertyOnYourItems"/>
        </CollectionViewSource.SortDescriptions>
    </CollectionViewSource>
    
    <ListBox ItemsSource="{Binding Source={StaticResource SortedItems}}"/>
    

    您可能希望将字符串包装在自定义 VM 类中,以便更轻松地应用排序行为。

    【讨论】:

    • 谢谢,肯特!在 CollectionViewSource 上绑定 Source 属性是我缺少的链接。我很感激。在这种情况下,我不需要自定义 VM 类,所以我只保留了 PropertyName 属性,这显然适用于字符串集合。
    • 另外,对于任何旁观者来说,SortDescription 标记采用 Direction 属性。
    • 如果 ListBox 是 DataTemplate 的一部分,它表示作为项目列表的对象的属性,该怎么办。我不能以某种方式在 ListBox 内进行排序吗?
    • 你能告诉我们 smc 命名空间在哪里吗?我没有使用 Xaml 成功找到 SortDescription。
    • franssu 的评论:scm 包括来自 WindowsBase 程序集的“System.ComponentModel”命名空间。 (xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase")
    【解决方案2】:

    如果附加属性符合无代码条件,则可以使用以下代码:

    public static class Sort
    {
        public static readonly DependencyProperty DirectionProperty = DependencyProperty.RegisterAttached(
            "Direction",
            typeof(ListSortDirection?),
            typeof(Sort),
            new PropertyMetadata(
                default(ListSortDirection?),
                OnDirectionChanged));
    
        [AttachedPropertyBrowsableForType(typeof(ItemsControl))]
        public static ListSortDirection? GetDirection(ItemsControl element)
        {
            return (ListSortDirection)element.GetValue(DirectionProperty);
        }
    
        public static void SetDirection(ItemsControl element, ListSortDirection? value)
        {
            element.SetValue(DirectionProperty, value);
        }
    
        private static void OnDirectionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is ItemsControl { Items: { } items })
            {
                if (e.NewValue is ListSortDirection direction)
                {
                    items.SortDescriptions.Add(new SortDescription(string.Empty, direction));
                }
                else if (e.OldValue is ListSortDirection old &&
                         items.SortDescriptions.FirstOrDefault(x => x.Direction == old) is { } oldDescription)
                {
                    items.SortDescriptions.Remove(oldDescription);
                }
            }
        }
    }
    

    然后在 xaml 中:

    <ListBox local:Sort.Direction="Ascending"
             ... />
    

    SortDescription 类型的另一个附加属性可能在许多情况下都有意义。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-30
      • 2010-11-03
      • 2020-12-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多