У меня есть ViewModel в проекте MVVM, который привязан к WPFView, который содержит список, в который данные загружаются асинхронно при запуске поиска. Данные, возвращаемые моим поиском, содержат цены на одни и те же товары, купленные в разные дни. Мне нужно, чтобы элементы в моем списке были упорядочены по возрастанию по цене: как только мой BackgroundWorker возвращает элементы, они асинхронно добавляются в мой список и упорядочиваются по цене, что позволяет мне видеть лучшую цену, как только она будет обнаружена.
Лучшее решение, которое я нашел, - это наличие ObservableCollection в моей ViewModel и привязка его к ItemsSource моего ListBox. У меня есть BackgroundWorker, который запускает асинхронный поиск; Я подписан на DataReceived EventHandler объекта, выполняющего поиск, и уведомляю пользовательский интерфейс следующим образом:
void sniper_DataReceived(object sender, TEventArgs e)
{
Action dispatchAction = () => this.Results.Add(e.T);
_currentDispatcher.BeginInvoke(dispatchAction);
}
через диспетчера
private readonly Dispatcher _currentDispatcher;
Мне это кажется нормальным, но элементы не упорядочиваются так, как мне нужно, поэтому я обнаружил, что CollectionViewSource делает именно то, что мне нужно, простым способом.
Вот в чем проблема:
Если я установил для контекста данных своего списка значение CollectionViewSource, у меня меньше возможностей для разработки, я продолжаю видеть данные о времени разработки в своем списке, но теряю DataContext на вкладке «Данные» в Blend.
Итак, я сделал что-то, что, на мой взгляд, немного грязно: я назвал свой ListBox атрибутом x: Name и добавил немного кода в свой MainWindow.xaml, чтобы поменять источник данных моего именованного списка во время выполнения следующим образом:
public MainWindow()
{
InitializeComponent();
Closing += (s, e) => ViewModelLocator.Cleanup();
#region CollectionViewSource Escamotage
if (!ViewModelLocator.MainStatic.IsInDesignMode)
{
var cvs = new CollectionViewSource() { Source = ViewModelLocator.MainStatic.Results };
cvs.SortDescriptions.Add(new SortDescription("LowestPrice", ListSortDirection.Ascending));
this.TrainsListBox.ItemsSource = cvs.View;
}
#endregion
}
Как вы думаете, это можно считать грехом?