ICollectionView Sort не работает после смены источника

У меня есть метод, который запрашивает базу данных с использованием структуры сущностей и помещает результаты в файл ICollectionView. ICollectionView действует как ItemsSource для DataGrid. При первом запросе все работает нормально, но при повторном запросе данные не сортируются должным образом, несмотря на применение правильного SortDescriptions.

Вот мой код для запроса и группировки/сортировки данных:

    CollectionViewSource cvsRS;

    private ObservableCollection<productorder> rs;
    public ObservableCollection<productorder> RS
    {
        get { return rs; }
        set
        {
            if (rs != value)
            {
                rs = value;
                OnPropertyChanged("RS");
            }
        }
    }

    private ICollectionView rsView;
    public ICollectionView RSView
    {
        get { return rsView; }
        set
        {
            if (rsView != value)
            {
                rsView = value;
                OnPropertyChanged("RSView");
            }
        }
    }

    public void QueryDatabase()
    {

        RS = new ObservableCollection<productorder>(DatabaseEntities.productorders.Where(o => o.month.id == CurrentMonth.id));
        if (RS != null)
        {
            cvsRS.Source = RS;
            RSView = cvsRS.View;

            RSView.GroupDescriptions.Clear();
            RSView.GroupDescriptions.Add(new PropertyGroupDescription("producttype.productcategory.name"));
            RSView.GroupDescriptions.Add(new PropertyGroupDescription("producttype.name"));  

            RSView.SortDescriptions.Clear();
            RSView.SortDescriptions.Add(new SortDescription("producttype.productcategory.sortorder", ListSortDirection.Ascending));
            RSView.SortDescriptions.Add(new SortDescription("client.name", ListSortDirection.Ascending));
            RSView.Refresh();
            CurrentRecord = null;
            SelectedRecords = null;
        }
    }

Группировка работает нормально, но группы расположены не в правильном порядке в зависимости от сортировки. Я пробовал ряд возможных «исправлений» без успеха (например, добавление описаний сортировки/группировки непосредственно в CollectionViewSource, сортировка перед группировкой, удаление части сортировки/группировки, удаление SortDescriptions на CollectionViewSource не выполняет повторную сортировку при изменении свойства).

Кто-нибудь знает, как поддерживать порядок сортировки независимо от того, сколько запросов выполняется? Я открыт для альтернативных методов запроса отображения данных в DataGrid, если это может сработать.


person matthew_b    schedule 31.10.2016    source источник
comment
Я бы попробовал привязать источник (не назначать, а привязывать, используя экземпляр класса Binding) один раз к свойству ObservableCollection<T>, которое повышает PropertyChanged, когда вы даете ему новую коллекцию. Затем повторно заполните, изменив свойство. Либо добавьте новую коллекцию, либо очистите и заполните старую. Но никогда не прикасайтесь к cvsRS.Source, кроме как для первоначальной настройки Binding.   -  person 15ee8f99-57ff-4f92-890c-b56153    schedule 31.10.2016
comment
Надеюсь, я правильно интерпретировал это, я сделал это в своем конструкторе: cvsRS = new CollectionViewSource(); cvsRS.Source = new Binding("RS"); RSView = cvsRS.View; Но я получаю сообщение об ошибке: «System.Windows.Data.Binding» не является допустимым значением для свойства «Источник».   -  person matthew_b    schedule 31.10.2016
comment
Я сделал быстрый тест, и он сработал, как я и ожидал, поэтому я опубликовал ответ с примером того, как сделать привязку. Вставить это в комментарий было бы нечитаемо в любом случае.   -  person 15ee8f99-57ff-4f92-890c-b56153    schedule 31.10.2016


Ответы (1)


Попробуйте привязать свойство CollectionViewSource.Source к свойству ObservableCollection<T>. Настройте привязку в конструкторе модели представления. Тогда просто оставьте это в покое. Обновите ObservableCollection<T>, замените его и т. д. Пока это ObservableCollection<T> и его общедоступное свойство вызывает PropertyChanged всякий раз, когда вы его заменяете, все будет работать.

public MyViewModel()
{
    BindCollectionViewSource();
}

protected void BindCollectionViewSource()
{
    cvsRS = new CollectionViewSource();

    var binding = new Binding
    {
        Source = this,
        Path = new PropertyPath("RS")
    };
    BindingOperations.SetBinding(cvsRS, CollectionViewSource.SourceProperty, binding);
}

//  Since we're not going to be messing with cvsRS or cvsRS.View after the 
//  constructor finishes, RSView can just be a plain getter. The value it returns 
//  will never change. 
public ICollectionView RSView
{
    get { return cvsRS.View; }
}

Вы не можете просто назначить привязку к Source; это еще не все. Материал Source="{Binding RSView}", который вы видите в XAML, может выглядеть как присваивание, но некоторые детали скрыты для удобства. Binding активно что-то делает. Он должен знать, кто является целевым объектом.

Я заметил одну забавную вещь: я дал своему тестовому коду один PropertyGroupDescription и один SortDescription. Когда я добавлял элементы в коллекцию, они сортировались по группам. Затем, когда я вызвал RSView.Refresh(), он прибегал к ним без ссылки на группы. Не уверен, что понял, что он там делает.

person 15ee8f99-57ff-4f92-890c-b56153    schedule 31.10.2016
comment
Спасибо, Эд. Я реализовал приведенный выше код, но теперь мой DataGrid никогда не показывает никаких данных. Его ItemsSource привязано к RSView. Я также сохранил свой метод QueryDatabase таким же, за исключением удаления cvsRS.Source = RS; RSView = cvsRS.View; - person matthew_b; 31.10.2016
comment
А пока попробуйте RS.Clear() и добавьте в него элементы вместо создания новой коллекции. - person 15ee8f99-57ff-4f92-890c-b56153; 31.10.2016
comment
@matthew_b О-о-о, еще одну вещь, которую я забыл, может понадобиться RSView.Refresh(), когда что-то изменится. - person 15ee8f99-57ff-4f92-890c-b56153; 31.10.2016
comment
Да, это необходимо (только что проверил), хотя я это уже реализовал. Еще раз спасибо. - person matthew_b; 31.10.2016
comment
Большое спасибо, это отлично работает для меня! - person Morgane; 17.12.2020