WPF & MVVM: лучшая архитектура для трудоемких результатов поиска? - PullRequest
2 голосов
/ 11 августа 2010

Я проектирую архитектуру для модуля, в котором происходит поиск.поиск занимает некоторое время, и я хотел бы, чтобы пользовательский интерфейс был отзывчивым, поэтому я могу делегировать извлечение данных классу, который будет выполнять поиск в отдельном потоке.

Затем яможет иметь два варианта:

либо 1 °: метод поиска возвращает модель представления с пустыми данными в качестве возвращаемого значения (заполнитель), но после завершения процесса поиска члены модели представления будут обновлены ирезультат, отображаемый на экране благодаря привязке данных,

2 °: метод поиска не имеет никакого типа возврата, но как только процесс поиска завершен, возникает событие и передается модель представления с ее окончательными значениямив аргументах события, поэтому он может использоваться вызывающим кодом.(и в конечном итоге будет поглощен видом)

Есть какие-нибудь мысли по этому поводу?

РЕДАКТИРОВАТЬ: Конечно, с решением 1 ° я ссылаюсь на привязку данных WPF к объектам, возвращаемым поиском-результаты объектов-заполнителей

Ответы [ 4 ]

2 голосов
/ 12 августа 2010

Если вы используете BackgroundWorker, шаблон дизайна для вас.Вызовите свой метод поиска в обработчике событий DoWork и поместите результаты в свойство Results переданного в DoWorkEventArgs сообщения.

Обновите пользовательский интерфейс с результатами в обработчике событий RunWorkerCompleted(они будут в свойстве RunWorkerCompletedEventArgs объекта Results).

Если вы хотите обновить пользовательский интерфейс во время поиска, вызовите метод поиска ReportProgress и обновите пользовательский интерфейс вProgressChanged обработчик событий.Вы можете поместить все, что вам нравится, в свойство UserState ProgressChangedEventArgs, включая промежуточные результаты поиска, хотя вы должны быть осторожны, чтобы не пропустить какие-либо объекты, к которым будет обращаться фоновый поток, так как он продолжает выполняться.

0 голосов
/ 15 августа 2010

Вот что я сделал в недавнем проекте.

Свойство IsBusy - это то, что у меня есть в базовом классе для всех моих моделей представления.Это логическое значение, к которому может привязываться представление, если оно хочет отобразить какой-то ожидающий элемент управления, например спиннер или что-то подобное.

Поле _retrieveData - это просто действие, которое я настроил во время создания модели представления.Я делаю это, потому что viewmodel может получить свой список Cars несколькими различными способами - поэтому в _retrieveData может быть разный код в зависимости от используемого конструктора.После того, как _retrieveData получит данные, он установит личный покровитель, _cars с данными.Поэтому после завершения _retrieveData установка общедоступных Cars в значение с новыми данными в _cars вызывает PropertyChangedEvent, который позволяет представлению обновляться.

Таким образом, эффект заключается в том, что когда представление переходит для получения данныхв первый раз он сразу возвращается, но становится нулевым.Затем, через несколько секунд, он получает реальные данные.В течение этого времени пользовательский интерфейс реагирует.И также, IsBusy верен, если пользовательский интерфейс хочет сообщить пользователю, что он работает в фоновом режиме.

Не уверен, что это хороший способ справиться с этим, но пока он работает для меня.

public List<Car> Cars
{
   get
   {
       if (this._cars == null)
       {
           base.IsBusy = true;

           // Start a background thread to get the data...
           ThreadPool.QueueUserWorkItem(new WaitCallback(delegate(object nullObject)
           {
               this._retrieveData.Invoke();
               this.Cars = this._cars;
               base.IsBusy = false;
           }));

           // While waiting on the background thread, return null for now.  When the background thread
           // completes, the setter will raise OnPropertyChanged and the view will know its time to bind...
           return this._cars;
       }

       return this._cars;
   }
   set
   {
       this._cars = value;
       base.OnPropertyChanged("Cars");
   }

}

0 голосов
/ 12 августа 2010

Вы также можете использовать Приоритетное связывание (http://msdn.microsoft.com/en-us/library/system.windows.data.prioritybinding.aspx).. Оно обеспечивает быстрый / медленный выбор, и вам не нужно беспокоиться об обновлениях потоков. Если, конечно, вы не хотите добавлять визуальные эффекты, чтобы пользователь знал что-то происходит.

0 голосов
/ 11 августа 2010

Я бы воспользовался преимуществом связывания данных и связал бы ваш элемент управления представлением результатов поиска с наблюдаемой коллекцией результатов поиска и обновил бы эту коллекцию в вашей ViewModel из фонового рабочего потока. Тогда он не требует никаких обратных вызовов или обновлений сообщений в вашем коде, он просто работает так, как вы ожидаете, воспользовавшись преимуществами сантехники в WPF.

...