c# - Waiting for Navigation Complete to continue -
my team has been struggling best practices approach handling response navigation 3 weeks without definitive answer. have both wpf , windows phone 8 solution share common code base.
for phone 8, display our company's splash screen , start initializing our data. due our complex nature, have long list of steps initialize before application operational.
protected override void onnavigatedto(navigationeventargs e) { base.onnavigatedto(e); if (e.navigationmode == navigationmode.new) { beginappstartup(); return; } .... void beginappstartup() { // initialization of settings , environment
at point, need optionally display 5 different pages requesting additional data. check our commands, , if executable, navigate , optionally display communication page, login page, or several other possible pages.
if( condition ) displayloginpage();
in wpf, easy since have modal dialogs , can wait user's input before continuing. in asynchronous world of wp8, no longer have this.
to accommodate platform, have implemented wide array of attempts, including saving next command execute. place believe assured page closed in onnavigatedto of splash page.
protected override void onnavigatedto(navigationeventargs e) { base.onnavigatedto(e); if (e.navigationmode == navigationmode.back) { // if returning splash set page, check if there new actions perform if (_startupaction != null) { _startupaction(); return; }
unfortunately, marginally acceptable since login page doesn't close since of our action in ui thread. code continues, splash page hidden behind still visible login page.
we have tried out autoresetevents, since must navigate out of ui thread, can't block ui thread. we've tried task.run similar issues.
// doesn't work. void showloginpage() { if (condition) { _manualresetevent.reset(); navigationservice.navigate(new uri("/views/login.xaml", urikind.relative) _manualresetevent.waitone(); } }
we've tried async/await tasks, encounter similar problems. believe best solution, we're not having better luck previously.
so question: best practice navigating splash page, optionally login page, , await login page close before continuing?
this sounds common scenario, yet i'm baffled! answers.
it not difficult provide functionality similar modal dialog. i'm not sure if great ui design decision, can done. this msdn blog post describes how usercontrol
custom adorner. written in 2007, time there no async/await
nor wp8.
i'm going show how similar thing using popup
control (which present in both wpf , wp8) , async/await
. here's functional part:
private async void openexecuted(object sender, executedroutedeventargs e) { await showpopup(this.firstpopup); await showpopup(this.secondpopup); }
each popup can , should data-bound viewmodel
.
c# (a wpf app):
using system; using system.linq; using system.threading.tasks; using system.windows; using system.windows.controls; using system.windows.controls.primitives; using system.windows.input; namespace wpf_22297935 { public partial class mainwindow : window { // http://stackoverflow.com/q/22297935/1768303 public mainwindow() { initializecomponent(); } eventhandler processclosepopup = delegate { }; private void closeexecuted(object sender, executedroutedeventargs e) { this.processclosepopup(this, eventargs.empty); } // show 2 popups modal-like ui flow private async void openexecuted(object sender, executedroutedeventargs e) { await showpopup(this.firstpopup); await showpopup(this.secondpopup); } private void canexecute(object sender, canexecuteroutedeventargs e) { e.canexecute = true; } // helpers async task showpopup(popup popup) { var tcs = new taskcompletionsource<bool>(); eventhandler handler = (s, e) => tcs.trysetresult(true); this.processclosepopup += handler; try { enablecontrols(false); popup.isenabled = true; popup.isopen = true; await tcs.task; } { enablecontrols(true); popup.isopen = false; popup.isenabled = false; this.processclosepopup -= handler; } } void enablecontrols(bool enable) { // assume root panel control var rootpanel = (panel)this.content; foreach (var item in rootpanel.children.cast<uielement>()) item.isenabled = enable; } } }
xaml:
<window x:class="wpf_22297935.mainwindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" title="mainwindow" height="350" width="525"> <window.commandbindings> <commandbinding command="applicationcommands.open" canexecute="canexecute" executed="openexecuted" /> <commandbinding command="applicationcommands.close" canexecute="canexecute" executed="closeexecuted"/> </window.commandbindings> <dockpanel> <border padding="5"> <stackpanel> <stackpanel> <textblock>main:</textblock> <textbox height="20"></textbox> <button command="applicationcommands.open" horizontalalignment="left" width="50">open</button> </stackpanel> <popup name="firstpopup" allowstransparency="true" placement="center"> <border background="darkcyan" padding="5"> <stackpanel background="darkcyan" width="200" height="200" horizontalalignment="left"> <textblock>first:</textblock> <textbox height="20"></textbox> <button command="applicationcommands.close" horizontalalignment="left" width="50">close</button> </stackpanel> </border> </popup> <popup name="secondpopup" allowstransparency="true" placement="center"> <border background="darkgray" padding="5"> <stackpanel background="darkgray" width="200" height="200" horizontalalignment="left"> <textblock>second:</textblock> <textbox height="20"></textbox> <button command="applicationcommands.close" horizontalalignment="left" width="50">close</button> </stackpanel> </border> </popup> </stackpanel> </border> </dockpanel> </window>
Comments
Post a Comment