Сортировка 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 для этого столбца в коде С#?


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, это приведет к тому, что текст заголовка переместится в другое место в OriginalSource, но это проблема, с которой я пока могу мириться. Я знаю, что это быстрый и грязный обходной путь, и, вероятно, есть гораздо лучшие альтернативы, поэтому любые рекомендации будут оценены.

person Rich    schedule 23.11.2009