我该如何仅使用XAML而不需要后台代码来对ListBox进行排序?

43
我需要对一个绑定了DataContext的ListBox中的字符串进行排序,但是它由另一个组件通过DataContext绑定到视图模型上。所以我不能像这个例子中使用ObjectDataProvider在XAML中直接实例化视图模型。
在我的XAML中:
<ListBox ItemsSource="{Binding CollectionOfStrings}" />

在我的视图模型中:
public ObservableCollection<string> CollectionOfStrings
{
    get { return collectionOfStrings; }
}

在另一个组件中:

view.DataContext = new ViewModel();

没有后台代码!所以,仅使用XAML,我如何对ListBox中的项进行排序?同样,XAML不拥有视图模型的实例化。

2个回答

99

使用 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 类中,这样可以更轻松地应用排序行为。


1
谢谢,肯特!对于我来说,在CollectionViewSource上绑定Source属性是缺失的关键。我很感激。在这种情况下,我不想要一个自定义的VM类,所以我只是省略了PropertyName属性,显然对于字符串集合来说也可以正常工作。 - Eben Geer
4
提醒旁观者,SortDescription标记需要一个Direction属性。 - Eben Geer
3
如果ListBox是DataTemplate的一部分,代表着一个包含多个项的列表对象的属性,那么我能否在ListBox内部进行排序呢? - Ingó Vals
2
请问smc命名空间在哪里?我尝试使用Xaml找不到SortDescription。 - Ingó Vals
44
franssu的评论:scm 包含了来自 WindowsBase 程序集的 "System.ComponentModel" 命名空间。(xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase") - Shadow The Spring Wizard
显示剩余2条评论

0
如果附加属性符合无代码要求,则可以使用以下内容:
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的附加属性可能是有意义的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接