如何仅使用XAML对ListBox进行排序而不进行代码隐藏?

时间:2009-08-14 23:44:44

标签: wpf xaml sorting mvvm listbox

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

在我的XAML中:

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

在我的视图模型中:

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

在另一个组成部分:

view.DataContext = new ViewModel();

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

2 个答案:

答案 0 :(得分:83)

使用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 :(得分: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 的附加属性在许多情况下可能是有意义的。