Not able to navigate to pages on Windows Metro App using c# - c#

When my UserLogin page loads, i want to check for user database, and if it doesn't exist, or can't be read, i want to direct it to NewUser page.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
CheckForUser();
if (UserExists == false)
this.Frame.Navigate(typeof(NewUser));
}
The problem is that it never navigates to NewUser, even when i comment out the if condition.

Navigate can't be called directly form OnNavigatedTo method. You should invoke your code through Dispatcher and it will work:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
CheckForUser();
if (UserExists == false)
Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
() => this.Frame.Navigate(typeof(NewUser)));
}

This happens because your app tries to navigate before the current frame completely loaded. Dispatcher could be a nice solution, but you have to follow the syntax bellow.
using Windows.UI.Core;
private async void to_navigate()
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => this.Frame.Navigate(typeof(MainPage)));
}
Replace MainPage with your desired page name.
Call this to_navigate() function.

you can try this and see if this works
frame.Navigate(typeof(myPage)); // the name of your page replace with myPage
full example
var cntnt = Window.Current.Content;
var frame = cntnt as Frame;
if (frame != null)
{
frame.Navigate(typeof(myPage));
}
Window.Current.Activate();
or
if you want to use a 3rd party tool like Telerik try this link as well
Classic Windows Forms, Stunning User Interface

I see you override OnNavigatedTo method but do not call base method. It may be the source of problem.
Try calling base method before any logic:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
CheckForUser();
if (UserExists == false)
this.Frame.Navigate(typeof(NewUser));
}

Use Dispatcher.RunIdleAsync to postpone your navigation to another page until UserLogin page is completely loaded.

The others are correct, but since Dispatcher doesn't work from the view model, here's how to do it there:
SynchronizationContext.Current.Post((o) =>
{
// navigate here
}, null);

Related

My AdMob Ad only loading up when I navigate to another page then back

Is this because of the OnElementChanged event?
Can I load the ads when the app is starting?
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.View> e)
{
base.OnElementChanged(e);
if (e.OldElement == null)
{
var adView = new AdView(Context);
switch ((Element as AdBanner).Size)
{
case AdBanner.Sizes.Standardbanner:
adView.AdSize = AdSize.Banner;
break;
...
}
adView.AdUnitId = "ca-app-pub-xxxxxxxxxxxxxxxx/xxxxxxxxxx";
var requestbuilder = new AdRequest.Builder();
adView.LoadAd(requestbuilder.Build());
SetNativeControl(adView);
}
}
I able to solve same issue by setting the VerticalOptions="FillAndExpand" and HorizontalOptions="FillAndExpand"
To create a native control in OnElementChanged in a renderer, test on e.NewElement != null and Control == null:
base.OnElementChanged(e);
if (e.NewElement != null && Control == null)
{
_adView = CreateNativeControl(...);
SetNativeControl(_adView);
}
According to the renderer documentation, the OnElementChanged method "is called when the Xamarin.Forms custom control is created to render the corresponding native control".
When the App is calling the OnElementChanged method at the start of the program it doesn’t showing up any ads. Only when it called to the second time.
I can't find the reason to issue happens, but after a doze of tries I found a workaround that worked for me, I did put the below code in end of OnAppearing override:
if (!this.initialized)
{
this.initialized = true;
this.adMobView.IsVisible = false;
Task.Run(async () =>
{
await Task.Delay(delay).ConfigureAwait(false);
Device.BeginInvokeOnMainThread(() => this.adMobView.IsVisible = true);
});
}
Basically, I change the visibility of admob view to false and, after some time (test good delay values for you), I change it to true again.
That is far away from a good solution and a best one will be very welcome, but for now it worked for me and can be usefull temporarily.

OnAppearing check from which Page the User is comming in Xamarin.forms

Is there a way i can detect, from which page the user is coming inside of the OnAppearing event in a ContentPage? As well as by pushing a Page to the Navigation or poping it.
I'm trying to do something like this.
protected override void OnAppearing()
{
base.OnAppearing();
if(/*User comes from certain page*/){
//Do stuff
}else{
//Do other stuff
}
}
Using the NavigationStack you can view the Pages that have been pushed into the stack.
content.Appearing += (sender, e) =>
{
var pages = Application.Current.MainPage.Navigation.NavigationStack;
foreach (var page in pages)
{
System.Diagnostics.Debug.WriteLine(page.Title);
}
};
Thus, you just have to look at the second to last page to determine where you are coming from....
Something like:
Application.Current.MainPage.Navigation.NavigationStack.Reverse().Take(2).Last();

UWP: Conditionally Navigating from OnNaviagted to another page without input

When the application runs, I want to check a condition that will determine where the page navigates to. There isn't any input from the user so there isn't an Object sender. How can I accomplish this?
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
var Albums = await App.DataModel.GetAlbum();
if (Albums != null)
{
Frame.Navigate(typeof(ViewModel.AlbumView));
}
else
{
Frame.Navigate(typeof(ViewModel.AddAlbumView));
}
}
in the App.Xaml.cs there is line in the OnAppLaunchedEvent
rootframe.Navigate(typeof(MainPage));
replace this with your condition
var Albums = await App.DataModel.GetAlbum();
if (Albums != null)
{
Frame.Navigate(typeof(ViewModel.AlbumView));
}
else
{
Frame.Navigate(typeof(ViewModel.AddAlbumView));
}
and don't forget to bring your albums and viewmodel into app.
Just as a good practice make the viewModel static and ref it in
other pages that require it . this ensures u are following a SingleTon
pattern and u dont have multiple copies of ur Viewmodel at the same time.

Caliburn.Micro Go Back called in On Activate not working in WinRT

This question is specific to Windows Phone 8.1 (WinRT); it may also be applicable Windows 8.1. I am using Caliburn.Micro 2.0.1
In my ViewModel's OnActivate I check whether an item is a database, if it isn't, I want to navigate back to the previous page.
The simplist solution will be just to call GoBack in the OnActivate method (this works in Windows Phone 8.0):
INavigationService _navigationService;
protected override void OnActivate()
{
_item = GetItemFromDB();
if(_item == null)
{
_navigationService.GoBack()
}
}
To navigate to the view model I call:
_navigationService.NavigateToViewModel<MyViewModel>(_param);
But it does not work, it ignores the GoBack call and stays on the page which I do not want to view.
When stepping through the code you can see that the GoBack code is called inside the NavigateToViewModel method; I expect this is the reason why it does not work (something to do with a queuing issue maybe?).
I have a very "hacky" solution that involves a timer (that works), but I really despise it since it is prone to threading issues and has the possibility of being called during the NavigateToViewModel call (if it takes long to finish), which will then again not work:
protected override void OnActivate()
{
_item = GetItemFromDB();
if(_item == null)
{
DispatcherTimer navigateBackTimer = new DispatcherTimer();
navigateBackTimer.Interval = TimeSpan.FromMilliseconds(300);
navigateBackTimer.Tick += GoBackAfterNavigation;
navigateBackTimer.Start();
}
}
public void GoBackAfterNavigation(object sender, object e)
{
_navigationService.GoBack();
(sender as DispatcherTimer).Stop();
}
Is there a better way to navigate back? Why doesn't the GoBack work in OnActivate? Is there a way to get it to work in OnActivate?
You can use
Execute.OnUIThreadAsync(() => /* navigationCode */);
instead of a timer to queue the action immediately after the processing of the current stack has finished.

How to Navigate to CameraCaptureTask from LensPicker

I have created a small sample Lens application, and I would like to be able to directly navigate to the CameraCaptureTask when the Lens icon is clicked in the default camera application. In my application I am already calling the CameraCaptureTask within a button click event during normal app operations. How might I set this up to work as well from the LensPicker option?
I have been referencing
http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj662936(v=vs.105).aspx
LensExampleUriMapper.cs
private string tempUri;
public override Uri MapUri(Uri uri)
{
tempUri = uri.ToString();
// Look for a URI from the lens picker.
if (tempUri.Contains("ViewfinderLaunch"))
{
// Launch as a lens, launch viewfinder screen.
return new Uri("/MainPage.xaml", UriKind.Relative);
}
// Otherwise perform normal launch.
return uri;
}
I was thinking of passing a QueryString value in return new Uri("/MainPage.xaml", UriKind.Relative); so that in my MainPage OnNavigatedTo event I could check that QueryString value and call the CameraCaptureTask, and then just route the result to the already existing event handler I have created (which displays the resulting image in MainPage). For some reason I am getting a debugging error when trying to create the QueryString to pass, and I am unsure of why?
EDIT** No longer getting error, but an infinite loop occurs when calling CameraCaptureTask. Why?
LensExampleUriMapper.cs
private string tempUri;
public override Uri MapUri(Uri uri)
{
tempUri = uri.ToString();
// Look for a URI from the lens picker.
if (tempUri.Contains("ViewfinderLaunch"))
{
// Launch as a lens, launch viewfinder screen.
return new Uri("/MainPage.xaml?fromLensPicker=" + "fromLensPicker", UriKind.Relative);
}
// Otherwise perform normal launch.
return uri;
}
MainPage.xaml.cs
protected override void OnNavigatedTo(NavigationEventArgs e)
{
string fromLensPicker = null;
if (NavigationContext.QueryString.TryGetValue("fromLensPicker", out fromLensPicker))
{
if (fromLensPicker == "fromLensPicker")
{
newButton_Click(null, null); //click event that calls CameraCaptureTask
fromLensPicker = null; //Temporarily nullifies value until MainPage is OnNavigatedTo after CameraCaptureTask completes
}
}
}
I believe that when CameraCaptureTask is called, the application is tombstoned and then resumed on MainPage, in which the QueryString value fromLensPicker == "fromLensPicker" and the entire cycle starts over again, repetitively. How might I solve this?
Use NavigationMode property in MainPage. I think you can't clear QueryString. But you can check how navigation to your page occured to know if its returning from CameraCaptureTask
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if(e.NavigationMode == NavigationMode.New)
// continue further
}
or
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if(e.NavigationMode == NavigationMode.Back)
return;
// else continue further
}
Instead of making fromLensPicker = null in MainPage.xaml.cs, I now have NavigationContext.QueryString.Remove("fromLensPicker") as referenced from WP7 Navigation with parameters
MainPage.xaml.cs
protected override void OnNavigatedTo(NavigationEventArgs e)
{
string fromLensPicker = null;
if (NavigationContext.QueryString.TryGetValue("fromLensPicker", out fromLensPicker))
{
if (fromLensPicker == "fromLensPicker")
{
NavigationContext.QueryString.Remove("fromLensPicker");
//Perform Action
}
}
}

Categories

Resources