Das App-Template verwendet den aktuellen Dispatcher von der Applikation Application.Current.Dispatcher
, um zum Beispiel den aktuellen Dispatcher in das ViewModel zu injizieren. Somit steht immer der richtige Dispatcher zur Verfügung und Code, welcher auf dem UIThread ausgeführt werden muss, kann einfach über unseren DispatchManager ausgeführt werden. Das passiert im BaseViewModel
und alle weiteren ViewModels
, welche von dieser Klasse erben, muss der Dispatcher wie unten zugewiesen werden.
Constructor (ctor)
Damit eine View bzw. ein ViewModel auch den Dispatcher empfangen kann, muss der Ctor wie folgt angepasst werden (sofern Ihr eine neue View bzw. ein neues ViewModel anlegt).
ViewModel
Das neue ViewModel sollte immer vom BaseViewModel oder AppViewModel erben. Damit erhält es Zugriff auf alle gemeinsam genutzten Funktionen und Methoden. Der Ctor kann als Parameter einen IDispatcher
annehmen, und diesen auch an die Basis-Klasse weitergeben. Andernfalls wird einfach der aktuelle Dispatcher
der Applikation gesetzt.
public partial class BaseViewModel { #region Ctor public BaseViewModel() { Dispatcher = Application.Current.Dispatcher; } public BaseViewModel(IDispatcher dispatcher) { Dispatcher = dispatcher; } #endregion // Some code... } // Custom ViewModel public partial class DashboardPageViewModel : BaseViewModel { #region Ctor public DashboardPageViewModel() : base(dispatcher) { Dispatcher = Application.Current.Dispatcher; } #endregion // Some code... }
Views
In der View muss der Ctor dann das gewünschte ViewModel als Parameter übergeben werden.
public partial class DashboardPage : ContentPage { public DashboardPage() { InitializeComponent(); var viewModel = new DashboardPageViewModel(); BindingContext = viewModel; } }
DispatchManager
Der DispatchManager ist eine Helper-Klasse, welche es Ihnen einfach ermöglicht Code über den Dispatcher auszuführen. Durch das vorgeschaltete trycatch werden auch direkt Fehler abgefangen und protokoliert (EventManger).
Einfaches Beispiel
Hier wird die Eigenschaft “IsRefreshing” Thread-Safe auf “false” gesetzt.
DispatchManager.Dispatch(Dispatcher, () => IsRefreshing = false);
Da es sich bei dieser Eigenschaft um ein Element handelt, welches ein Binding auf ein UI-Element hat, muss dieses zwangsweise am MainThread der Applikation ausgeführt werden. Andernfalls kann es hier zu einer Ausnahme bzw. einen Crash kommen.
CodeSnippet dispatchen
Um einen ganzen Codeblock zu dispatchen, kann die Funktion wie folgt aussehen.
DispatchManager.Dispatch(Dispatcher, () => { CurrentJobInfo = DemoManager.JobInfo; PrintersState = DemoManager.PrinterState.Printer; ServerSettings = DemoManager.ServerSettings; Files = DemoManager.Files; });
Dispatching abwarten
Manchmal kann es nötig sein, dass Dispatching abzuwarten (await). Dazu muss die DispatchAsync() Methode verwendet werden.
await DispatchManager.DispatchAsync(Dispatcher, UpdateFromInstanceData); // Or await DispatchManager.DispatchAsync(Dispatcher, () => { IsRefreshing = true; IsReachable = false; SelectedServer = Servers.FirstOrDefault(server => server.Id == LastServerId); SelectedServerAddress = SelectedServer?.FullWebAddress; }); await CheckOnlineStateSelectedServer();