Как передать Диспетчера UI ViewModel

Я, как предполагается, могу получить доступ к Диспетчеру, который принадлежит Представлению, я должен передать его ViewModel. Но Представление ничего не должно знать о ViewModel, поэтому как Вы передаете его? Представьте интерфейс, или вместо того, чтобы передать его экземплярам создают глобальный одиночный элемент диспетчера, который будет записан Представлением? Как Вы решаете это в своих приложениях MVVM и платформах?

Править: Обратите внимание, что, так как мой ViewModels мог бы быть создан в фоновых потоках, которые я не могу просто сделать Dispatcher.Current в конструкторе ViewModel.

69
задан Adi Lester 29 May 2012 в 07:52
поделиться

4 ответа

Я абстрагировал Диспетчер с помощью интерфейса IContext :

public interface IContext
{
   bool IsSynchronized { get; }
   void Invoke(Action action);
   void BeginInvoke(Action action);
}

Это дает то преимущество, что вы можете более легко тестировать свои модели просмотра.
Я добавляю интерфейс в свои модели просмотра, используя MEF (структуру управляемой расширяемости). Другой возможный вариант - аргумент конструктора. Однако мне больше нравится инъекция с использованием MEF.

Обновление (пример из ссылки pastebin в комментариях):

public sealed class WpfContext : IContext
{
    private readonly Dispatcher _dispatcher;

    public bool IsSynchronized
    {
        get
        {
            return this._dispatcher.Thread == Thread.CurrentThread;
        }
    }

    public WpfContext() : this(Dispatcher.CurrentDispatcher)
    {
    }

    public WpfContext(Dispatcher dispatcher)
    {
        Debug.Assert(dispatcher != null);

        this._dispatcher = dispatcher;
    }

    public void Invoke(Action action)
    {
        Debug.Assert(action != null);

        this._dispatcher.Invoke(action);
    }

    public void BeginInvoke(Action action)
    {
        Debug.Assert(action != null);

        this._dispatcher.BeginInvoke(action);
    }
}
45
ответ дан 24 November 2019 в 13:48
поделиться

В некоторых моих проектах WPF я столкнулся с такой же ситуацией. В моей модели MainViewModel (экземпляр Singleton) я получил статический метод CreateInstance (), который принимает диспетчер. И экземпляр create вызывается из View, чтобы я мог передать Dispatcher оттуда. А тестовый модуль ViewModel вызывает CreateInstance () без параметров.

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

-1
ответ дан 24 November 2019 в 13:48
поделиться

Я получаю ViewModel для сохранения текущего диспетчера в качестве члена.

Если ViewModel создается представлением, вы знаете, что текущий диспетчер во время создания будет диспетчером представления.

class MyViewModel
{
    readonly Dispatcher _dispatcher;
    public MyViewModel()
    {
        _dispatcher = Dispatcher.CurrentDispatcher;
    }
}
15
ответ дан 24 November 2019 в 13:48
поделиться

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


РЕДАКТИРОВАТЬ:

Это редактирование является ответом на комментарий Исака Саво.

Внутри кода Microsoft для обработки привязки к свойствам вы найдете следующий код:

if (Dispatcher.Thread == Thread.CurrentThread)
{ 
    PW.OnPropertyChangedAtLevel(level);
} 
else 
{
    // otherwise invoke an operation to do the work on the right context 
    SetTransferIsPending(true);
    Dispatcher.BeginInvoke(
        DispatcherPriority.DataBind,
        new DispatcherOperationCallback(ScheduleTransferOperation), 
        new object[]{o, propName});
} 

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

18
ответ дан 24 November 2019 в 13:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: