質問

I am looking for a smart way of binding a ListView DataSource property to the set (any collection) of IComparable custom objects. I would like to have a control real time responding to changes of my collection and have results (in ListView) sorted using provided by the Interface method.

I suppose that it can be done by creating custom collection inheriting from ObservableCollection<T> or SortedSet<T> and binding to such class (which combines the advantages of both). I am new to WPF binding and searching for any hints.

役に立ちましたか?

解決

You can do this by using CollectionViewSource, descendants of which wrap all collections used by WPF controls. You'll need to implement IComparer though. Here I use a helper class ComparableComparer<T> which uses IComparable<T> implementation, but you can put your logic into the Foo class if you want.

MainWindow.xaml

<Window x:Class="So16368719.MainWindow" x:Name="root"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <ListView ItemsSource="{Binding FooItemsSource, ElementName=root}">
        <ListView.View>
            <GridView>
                <GridViewColumn DisplayMemberBinding="{Binding Name}"/>
            </GridView>
        </ListView.View>
    </ListView>
</Window>

MainWindow.xaml.cs

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows.Data;

namespace So16368719
{
    public partial class MainWindow
    {
        public ObservableCollection<Foo> FooItems { get; set; }
        public ListCollectionView FooItemsSource { get; set; }

        public MainWindow ()
        {
            FooItems = new ObservableCollection<Foo> {
                new Foo("a"), new Foo("bb"), new Foo("ccc"), new Foo("d"), new Foo("ee"), new Foo("ffff")
            };
            FooItemsSource = (ListCollectionView)CollectionViewSource.GetDefaultView(FooItems);
            FooItemsSource.CustomSort = new ComparableComparer<Foo>();
            InitializeComponent();
        }
    }

    public class Foo : IComparable<Foo>
    {
        public string Name { get; set; }

        public Foo (string name)
        {
            Name = name;
        }

        public int CompareTo (Foo other)
        {
            return Name.Length - other.Name.Length;
        }
    }

    public class ComparableComparer<T> : IComparer<T>, IComparer
        where T : IComparable<T>
    {
        public int Compare (T x, T y)
        {
            return x.CompareTo(y);
        }

        public int Compare (object x, object y)
        {
            return Compare((T)x, (T)y);
        }
    }
}

Note:

  • Implementation of ComparableComparer<T> is quick and dirty. It should also check for nulls.
  • You should use MVVM pattern and not code-behind.

External links:

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top