Page navigation event - c#

I was reading trough the documentation for UWP and I got stuck a little.
I have few pages that connect to WCF service taking some information of it few of them download pictures and take few seconds to load.
So I've decided to implement a loading screen while they load however when I try using
this.Frame.Navigate(typeof(page));
I get stuck in a deadlock state everything freezes while the new page is loading I've tried putting on pageloading event on the other page but this is not helping much since its still locked on the last form.
Does anyone know the right event that I need to call when calling this.Frame.Navigate() so I can initialize my loading control while the new frame is loaded?

Navigate to Loading Screen
this.Frame.Navigate(typeof(LoadingScreen));
In OnNavigatedTo event in LoadingScreen "download pictures"
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
await DownloadPictures();
//After downloading, navigate to the next page
this.Frame.Navigate(typeof(page));
}

try launching the view on a separate window like this
try
{
CoreApplicationView Nv= CoreApplication.CreateNewView();
var z = CoreApplication.MainView;
int id= 0;
await
Nv.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
Frame frame = new Frame();
frame.Navigate(typeof(page));
Window.Current.Content = frame;
// You have to activate the window in order to show it later.
Window.Current.Activate();
id= ApplicationView.GetForCurrentView().Id;
});
bool viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(id);
}
catch (Exception eee)
{
Windows.UI.Popups.MessageDialog errorBox =
new Windows.UI.Popups.MessageDialog("Couldn't Create New
Window: " + eee.Message);
await errorBox.ShowAsync();
}

Related

Xamarin/Tizen: Executing Navigation.PopAsync() crashes the app

I have a navigation page that sets up three pages. The first page loads, the user has to pick an option from a listview and then it loads the second page with PushAsync(). At this point the user can now navigate between the three pages by turning the clock face. If I call PopToRootAsync() on the second page it works fine. If the rotary clock face is turned clockwise it loads a third page via PushAsync().
The problem is if I call PopAsync() on that third page OR I change the PopToRootAsync() on the second page to a PopAsync(), the app crashes. I have no way to determine what the error is either as I just get segmentation fault and nothing is written to the Tizen log that is seemingly indicative of why it crashed.
Is there some reason that a PopAsync() would cause this? I know I saw some other articles this could occur if the MainPage is not loaded into a NavigationPage but I'm doing that. I've been looking through stuff and writing debug logs for days but have nothing to show for it. Any help would be more than appreciated. Thank you!
App.cs
public App()
{
MainPage = new NavigationPage(new ServerSelectionPage());
}
ServerSelection.cs
private void ServerSelection_OnItemTapped(object sender, ItemTappedEventArgs args)
{
App.SERVER = (Server)args.Item;
Navigation.PushAsync(new ArrowsPage());
}
PageBase.cs
public async void Rotate(RotaryEventArgs args)
{
Page _currentPage = Page.REMOTE_BUTTONS;
if (this.GetType() == typeof(ButtonsPage))
_currentPage = Page.REMOTE_BUTTONS;
else if (this.GetType() == typeof(ArrowsPage))
_currentPage = Page.REMOTE_ARROWS;
else
_currentPage = Page.SERVER_SELECTION;
// When rotating (previous rotation is ongoing, do nothing)
if (_rotating)
{
return;
}
_rotating = true;
if (!(App.SERVER is null))
{
if (_currentPage == Page.SERVER_SELECTION)
{
if (args.IsClockwise)
await Navigation.PushAsync(new ArrowsPage());
}
else if (_currentPage == Page.REMOTE_DIRECTIONAL)
{
if (args.IsClockwise)
await Navigation.PushAsync(new ButtonsPage());
else
await Navigation.PopToRootAsync();
}
else
{
try
{
if (!args.IsClockwise)
await Navigation.PopAsync(); // This will crash the app
}
catch(Exception ex)
{
Log.Debug(ex.Message);
}
}
}
_rotating = false;
}
After reading the comment by #vin about checking if the Navigation object is null I suddenly had the thought that it may not be the Navigation page but the RotaryFocusObject. So I changed
if (!args.IsClockwise)
await Navigation.PopAsync();
to
if (!args.IsClockwise)
{
RotaryFocusObject = null;
await Task.Delay(300);
await Navigation.PopAsync();
}
and it no longer crashes. The delay is necessary as if you call PopAsync right after setting the object to null it can still sometimes crash.
So apparently if you pop the current page it causes an error as the focus of the rotary dial is still set to the current navigation page. Why this error does not seemingly occur if you use the Navigation.PopToRootAsync() makes no sense to me.
Navigation.PopToRootAsync() and Navigation.PopToRootAsync() are causing destroy of Page renderer, and the Rotate handler is belong to Page Renderer,
If Page renderer was deleted before completion of Rotate Native Callback that is belong to Page renderer, it will be crashed.
await Task.Delay() let to returning native callback.

Initialize topmost UWP window from the constructor

Weird issue.
I'm trying to build a desktop app that has an option to open a second "window".
So Foo opens Bar.
Only Bar should, by default, be a topmost window.
The below method works just fine, when called by a button click.
private async Task<bool> MakeTopMost()
{
await ApplicationView.GetForCurrentView().TryEnterViewModeAsync(ApplicationViewMode.CompactOverlay);
}
However, when called from the page constructor, via an Action,
new Action(async () => await MakeTopMost())();
...
Lo and behold. Nothing happens. I've tried the Loaded event also. No dice.
What am I missing?
Edit:
A workaround would be the button clicked to open a new app also makes the app topmost. Like so:
private async void ShowCompactView()
{
var compactViewId = ApplicationView.GetForCurrentView().Id;
await CoreApplication.CreateNewView().Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
var frame = new Frame();
frame.Navigate(typeof(BAR));
Window.Current.Content = frame;
Window.Current.Activate();
ApplicationView.GetForCurrentView().Title = "CompactOverlay Window";
});
bool viewShown = await ApplicationViewSwitcher.TryShowAsViewModeAsync(compactViewId, ApplicationViewMode.CompactOverlay);
}
But that makes the whole app topmost (not just a page).
What I basically did in the method posted last in the question was
Get the id of the application page currently displayed
Open a new page.
Compact overlay the id. Which was the main page. So basically the entire app was set as topmost.
So, by using a variable to hold the id of the newly opened page, the BAR, we can open a page from FOO that's automatically set as topmost.
private int _barID;
private async void ShowCompactView()
{
await CoreApplication.CreateNewView().Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
var frame = new Frame();
frame.Navigate(typeof(Bar));
_barID = ApplicationView.GetForCurrentView().Id;
Window.Current.Content = frame;
Window.Current.Activate();
ApplicationView.GetForCurrentView().Title = "CompactOverlay Window";
});
bool viewShown = await ApplicationViewSwitcher.TryShowAsViewModeAsync(sliderID, ApplicationViewMode.CompactOverlay);
}
it should have been obvious.

Bring the UWP app to the front of current window

How can i use
await Windows.System.Launcher.LaunchUriAsync(new Uri("protocol://"));
to navigate to specific view of uwp application.
Is there any way to bring the app in front of the screen, if app was minimized or hidden behind other apps?
Thanks in advance
How can i use await Windows.System.Launcher.LaunchUriAsync(new Uri("protocol://")); to navigate to specific view of uwp application
For this, firstly you need to add the Protocol declaration in your Package.appxmanifest file . (Go to declarations tab and add Protocol from the available protocols). ( MSDN Doc )
Here i am using "app-protocol" as the protocol name.
Once this is done, you need to override the OnActivated() method in your App.xaml.cs. This method will be called when the app is launched using the protocol.
The arguments that we pass when calling the protocol can be retrieved here and based on that you can show your page or maybe pass that parameter to your page and let it handle the navigation .
For instance, if our Uri is app-protocol:login?param1=true, when you receive the ProtocolActivatedEventArgs eventArgs in the onActivated() method you will have access to the whole Uri.
You can use eventArgs.Uri to access all the Uri properties.
In any case your code should look something like this :
C#
protected override void OnActivated(IActivatedEventArgs args)
{
if (args.Kind == ActivationKind.Protocol)
{
ProtocolActivatedEventArgs eventArgs = args as ProtocolActivatedEventArgs;
// Get the root frame
Frame rootFrame = Window.Current.Content as Frame;
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (rootFrame == null)
{
// Create a Frame to act as the navigation context and navigate to the first page
rootFrame = new Frame();
rootFrame.NavigationFailed += OnNavigationFailed;
if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
//TODO: Load state from previously suspended application
}
// Place the frame in the current Window
Window.Current.Content = rootFrame;
}
//URI : app-protocol:login?param1=true
//Logic for showing different pages/views based on parameters passed
if (eventArgs.Uri.PathAndQuery != string.Empty)//PathAndQuery:login?param1=true
{
var absolutePath = eventArgs.Uri.AbsolutePath;//AbsolutePath:login
if (absolutePath.Equals("login"))
{
rootFrame.Navigate(typeof(LoginPage));
}
else
{
rootFrame.Navigate(typeof(MainPage));
}
}
else
{
rootFrame.Navigate(typeof(MainPage));
}
}
// Ensure the current window is active
Window.Current.Activate();
}
Is there any way to bring the app in front of the screen, if app was minimized or hidden behind other apps?
We are calling Window.Current.Activate(); to ensure this.
To bring any UWP window to the front use this snippet (works if window with given viewId was already created and is either minimized or behind other windows:
private async Task TryActivateViewAsync(viewId)
{
if (Window.Current.Dispatcher != null)
{
await Window.Current.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{
if (await ApplicationViewSwitcher.TryShowAsStandaloneAsync(viewId))
{
await ApplicationViewSwitcher.SwitchAsync(viewId);
}
});
}
}
Just as a reminder, viewId is an Identifier of a window which you can get when you create that window using:
var coreView = CoreApplication.CreateNewView(); // creates new view
await coreView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
_someViewId = ApplicationView.GetForCurrentView().Id; // gets that view's id
}

Could not create a new view because the main window has not yet been created

I'm having a problem with my app during the start up. I'm getting at exception that says
A method was called at an unexpected time. Could not create a
new view because the main window has not yet been created
First I display a splash screen so I can get some data from the internet in the background. My splash screen works fine and I implemented it correctly as indicated in the documentation.
In App.xaml.ca I have some standard code for splash screen
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
...
if (e.PreviousExecutionState != ApplicationExecutionState.Running)
{
bool loadState = (e.PreviousExecutionState == ApplicationExecutionState.Terminated);
ExtendedSplash extendedSplash = new ExtendedSplash(e.SplashScreen, loadState);
Window.Current.Content = extendedSplash;
}
...
Window.Current.Activate();
}
Then in my App constructor I have this
public static Notifications notifications;
public App()
{
Microsoft.ApplicationInsights.WindowsAppInitializer.InitializeAsync(
Microsoft.ApplicationInsights.WindowsCollectors.Metadata |
Microsoft.ApplicationInsights.WindowsCollectors.Session);
this.InitializeComponent();
this.Suspending += OnSuspending;
SomeClass.RunTasks(); //acquire data from a REST service
//initializing the object for subscribing to push notification, not sure if this is the best place to put this.
App.notifications = new Notifications("hubname", "myEndpoint");
}
The exception occurs inside my RunTasks() method which looks like this
public class SomeClass
{
GetHTTPResponse _aggregateData = new GetHTTPResponse("http://someRestService");
public async void RunTasks()
{
try
{
HttpResponseMessage aggregateData = await _aggregateData.AcquireResponse();
await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
() =>
{
//do a bunch of stuff with the data
//NOTE: I am making updates to my ViewModel here with the data I acquired
//for example App.ViewModel.Time = somevalue
//when finished dismiss the splash screen
ExtendedSplash.Instance.DismissExtendedSplash();
}
);
}
catch (System.Exception ex)
{
}
}
}
Any ideas how I can improve this and eliminate the error?
Could it have something to do with me updating my ViewModel items (which are data bound to UI components)?
EDIT when I remove the creation of my notifications object from App.cs constructor (and move it into the RunTasks() method, the error goes away.
App.notifications = new Notifications("hubname", "myEndpoint");
The reason you get the exception is because Windows.ApplicationModel.Core.CoreApplication.MainView is not valid in your application's constructor as the main view has not been created yet.
You can access it once you have received the Application.OnLaunched/OnActivated event.
Thanks!
Stefan Wick -
Windows Developer Platform

Strange behavior while page navigation in wp 8.1

I am making a Wp 8.1 app.
I have this "reader" page. Its constructor is -
public Reader()
{
this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Enabled;
initalizeTimers();
initAd();
}
and the onNvaigatedTo
protected override void OnNavigatedTo(NavigationEventArgs e)
{
HardwareButtons.BackPressed += Hardware_backPressedLocal;
var x = (Tuple<int, string, Global.FileType>)e.Parameter;
//load settings here
loadColorSchemes();
setStatusBarColor();
if (e.NavigationMode == NavigationMode.Back)
{
readerVm.refreshWebView();
return;
}
if (x != null)
{
initalizeReader(x);
}
}
The initalizeReader() is an async method. The page has a grid in front for showing the wait msg, and the initializeReader method hides that grid.
Problem:
On tapping a button which calls the Frame.Navigate() method to the reader page, sometimes the reader page loads with waiting grid which hides after sometime (expected) and at other times the UI freezes and then the reader page loads with waiting grid already hidden. And 70-80 % time the UI freezes.
Can you tell whats going wrong here? And how to fix it?
Try to call your method initalizeReader(x); when the event Loaded from the page raised.
Also, if this method calls some async functions, call them asynchronously also.

Categories

Resources