Сортирайте WPF ListView с DataTemplate вместо DisplayMemberBinding

Работя с сортируем WPF ListView и вече постигнах голям напредък. Не е толкова трудно, тъй като вече има много неща в интернет. Но има малко информация, която все още ми липсва.

С такава колона:

<GridViewColumn Width="200" Header="Fahrzeugname" DisplayMemberBinding="{Binding Name}">

Мога да го сортирам така:

Binding columnBinding = column.DisplayMemberBinding as Binding;

if (columnBinding != null)
{
    sorts.Clear();
    sorts.Add(new SortDescription(columnBinding.Path.Path, direction));
    lastColumnSorted = column;
}

Но проблемът ми е, че нямам DisplayMemberBinding, тъй като използвам DataTemplate:

<DataTemplate>
    <TextBlock Text="{Binding Name}" TextAlignment="Left"/>
</DataTemplate>

Как да получа свойството Binding за тази колона в C# кода?


person TalkingCode    schedule 03.08.2009    source източник


Отговори (4)


Написах набор от прикачени свойства, за да направя точно това, което Кент предложи, можете да го проверите тук


РЕДАКТИРАНЕ: както е поискано, ето примерна команда за GridViewSort.Command:

    private ICommand _sortCommand;
    public ICommand SortCommand
    {
        get
        {
            if (_sortCommand == null)
            {
                _sortCommand = new RelayCommand(SortPersonsBy);
            }
            return _sortCommand;
        }
        set { _sortCommand = value; }
    }

    private void SortPersonsBy(object param)
    {
        string propertyName = param as string;
        ICollectionView view = CollectionViewSource.GetDefaultView(_persons);
        ListSortDirection direction = ListSortDirection.Ascending;
        if (view.SortDescriptions.Count > 0)
        {
            SortDescription currentSort = view.SortDescriptions[0];
            if (currentSort.PropertyName == propertyName)
            {
                if (currentSort.Direction == ListSortDirection.Ascending)
                    direction = ListSortDirection.Descending;
                else
                    direction = ListSortDirection.Ascending;
            }
            view.SortDescriptions.Clear();
        }
        if (!string.IsNullOrEmpty(propertyName))
        {
            view.SortDescriptions.Add(new SortDescription(propertyName, direction));
        }
    }

(той всъщност прилага същото поведение, както когато GridViewSort.AutoSort е зададено на true...)

person Thomas Levesque    schedule 03.08.2009
comment
Страхотна статия! Пример за GridViewSort.Command ще бъде добре. Тъй като не съм толкова опитен с тази тема. - person TalkingCode; 03.08.2009

вграденият в WPF начин би бил да се използва ICollectionView.

ICollectionView view = CollectionViewSource.GetDefaultView(yourItemsSourceList);
if(view.CanSort)
{
   view.SortDescriptions.Add(...)
}
person Martin Moser    schedule 03.08.2009

Защо бихте се опитвали да направите това автоматично? Защо не предоставите прикачено свойство, което потребителите могат да задават, за да диктуват свойството, по което трябва да се сортира колоната?

<GridViewColumn s:SortableColumn.SortBy="{Binding Name}" ...>

По този начин предлагате повече свобода на внедряване и кодът ще бъде по-бърз и по-стабилен.

person Kent Boogaart    schedule 03.08.2009

Изправен съм пред подобен проблем със сортирането на WPF Listview/Gridview и имам някои ограничения, което затруднява прилагането на предоставените решения на CSharp. По същество имам съществуващо ASP.NET приложение с хиляди редове с дебъгван VB код, както и работещ SQL за база данни с над 100 таблици и някои много сложни съединения. Трябва да напиша Windows .exe въз основа на същото приложение, но искам да използвам WPF, за да внедря подобен графичен вид и усещане.

След като приключих с отказа от отговорност, срещнах проблема със сортирането и потърсих в интернет всички страхотни споделени концепции като тези по-горе и се опитах да ги конвертирам от CS във VB. Аз съм опитен програмист, но открих, че това е просто извън обсега ми, така че се обърнах към друго и вместо това разработих свой собствен сорт. Вероятно ще ужаси пуристите, но аз съм прагматик и създаването на комерсиално приложение има предимство.

За да сортирам мрежата, реших просто да използвам събитията на мишката върху заглавките на колоните. DoubleClick за възходящо сортиране и MouseRightButtonUp за низходящо.

<GridViewColumn Header="Project Name &#160;&#160;" Width="300" >

Private Sub ListViewGrid_MouseDoubleClick(
    ByVal sender As Object, ByVal e As System.Windows.Input.MouseButtonEventArgs) Handles ListingDG.MouseDoubleClick

    Try
        Dim mouseHdrClick As String = DirectCast(DirectCast(e.OriginalSource, System.Object), System.Windows.Controls.TextBlock).Text
        Dim SqlOrderBy As String = ""

        Select Case UCase(mouseHdrClick.Trim)
            Case UCase("Product Name")
                SqlOrderBy = " ORDER BY Product_Name"

След това просто презареждам ListViewGrid с помощта на низовата променлива SqlOrderBy. Единственият проблем, който срещнах, беше, че бях принуден да щракна върху текста на заглавката в заглавката на колоната, за да работи. Реших това, като просто добавих знака за интервал в XML (&#160;), за да запълня ширината на колоната. Командата .Trim ги изчиства отново, за да работи Select Case. Все още не съм измислил как да добавя малките стрелки нагоре и надолу, но функционалността е това, което има значение тук, тъй като това са само козметични щрихи в момента.

<GridViewColumn Header="Project Name &#160;&#160;" Width="300">

Накрая позволете ми да добавя, че съм напълно наясно, че ако променя структурата на Gridview, това ще накара текста на Header да се премести другаде в OriginalSource, но това е проблем, с който мога да живея засега. Знам, че това е бързо и мръсно решение и вероятно има много по-добри алтернативи, така че всякакви препоръки ще бъдат оценени.

person Rich    schedule 23.11.2009