Ответ 1
Я обычно использую Application.Current.Dispatcher
: поскольку Application.Current
является статическим, вам не нужна ссылка на элемент управления
Так сказать в среде MVVM, я в фоновом потоке, и я хотел бы запустить обновление на элементе управления ui. Так что обычно я бы пошел myButton.Dispatcher.BeginInvoke(blabla), но у меня нет доступа к myButton (потому что в viewmodel нет доступа к элементам управления представлением). Итак, какова нормальная модель для этого?
(я предполагаю, что он всегда привязан, но я хотел бы знать, как это сделать через диспетчер)
Я обычно использую Application.Current.Dispatcher
: поскольку Application.Current
является статическим, вам не нужна ссылка на элемент управления
Из Caliburn Micro исходный код:
public static class Execute
{
private static Action<System.Action> executor = action => action();
/// <summary>
/// Initializes the framework using the current dispatcher.
/// </summary>
public static void InitializeWithDispatcher()
{
#if SILVERLIGHT
var dispatcher = Deployment.Current.Dispatcher;
#else
var dispatcher = Dispatcher.CurrentDispatcher;
#endif
executor = action =>{
if(dispatcher.CheckAccess())
action();
else dispatcher.BeginInvoke(action);
};
}
/// <summary>
/// Executes the action on the UI thread.
/// </summary>
/// <param name="action">The action to execute.</param>
public static void OnUIThread(this System.Action action)
{
executor(action);
}
}
Прежде чем использовать его, вы должны будете вызвать Execute.InitializeWithDispatcher()
из потока пользовательского интерфейса, тогда вы можете использовать его следующим образом: Execute.OnUIThread(()=>SomeMethod())
ViewModelBase Catel имеет свойство Dispatcher, которое вы можете использовать.
Я предпочитаю, чтобы мои объекты ViewModels наследовали от DependencyObject и гарантировали, что они построены на потоке пользовательского интерфейса, что прекрасно справляется с этой ситуацией - они имеют свойство Dispatcher
, которое соответствует диспетчеру потоков пользовательского интерфейса. Затем вам не нужно загрязнять ваше представление деталями реализации ViewModel.
Некоторые другие плюсы:
Application.Current.Dispatcher
)Вы можете поднять событие в своей модели просмотра (возможно, используя соглашение об именах, чтобы указать, что он будет поднят из потока, отличного от UI, например NotifyProgressChangedAsync). Тогда ваш View, который подключен к событию, может обращаться с диспетчером соответствующим образом.
Или вы можете передать делегат функции синхронизации в вашу модель просмотра (из вашего представления).
Передайте диспетчер потоков пользовательского интерфейса в конструктор ViewModel и сохраните его в виртуальной машине.
Обратите внимание, что каждый поток может иметь свой собственный диспетчер. Вам понадобится поток пользовательского интерфейса!