C# Xamarin.Forms ios Navigation.PushAsync not working properly - c#

I have xamrin.forms project with both Android and iOS. I have just simple 2 pages where i call one from the other. On android everything is working perfectly as it should but on iOS any call for forms (navigation.PushAsync, DisplayAlert, ...) is not working properly (does nothing) until I put application to the sleep (put it to the background ) and then when I reload it back everything starts to work perfectly.
This is how i create first page in App.xaml.cs
var page = new NavigationPage(new FirstPage());
MainPage = page;
Button command for my first page calls for this:
FormsNavigation.PushAsync(secondPage, true);
I allredy tried to wrap Push into Device.BeginInvokeOnMainThread but no result.

In Xamarin.Forms, when using a NavigationPage to navigate to a ContentPage, use await Navigation.PushAsync.
And, because all UI animations must be invoked on the Main UI Thread, I recommend wrapping it Device.InvokeOnMainThreadAsync.
async Task NavigateToSecondPage()
{
var secondPage = new SecondPage();
await Device.InvokeOnMainThreadAsync(() => Navigation.PushAsync(secondPage, true));
}

Related

Why does OnAppearing not fire every time in Android

I have a Xamarin project. When I run in UWP OnAppearing initially fires once and then loads the Login Page. After successfully logging in, my Main page fires OnAppearing again and I load data into my ViewModel.
However, if I run the project in Android, OnAppearing only fires once - When the Main page initially loads.
protected override async void OnAppearing()
{
if (!App.IsUserLoggedIn)
{
await App.NavigationService.NavigateModalAsync(PageNames.LoginPage, false);
}
else
{
((SchedulerViewModel)Schedule.BindingContext).LoadData();
}
base.OnAppearing();
}
Why does Android only fire once? Or is UWP the one misbehaving?
NOTE: NavigationService is not a standard Xamarin Forms class. I assume it is built on top of Page.Navigation.PushModalAsync and PopModalAsync.
This is documented behavior of Modal Stack on Android:
Popping Pages from the Modal Stack:
When PopModalAsync is invoked, the following events occur:
...
The page being returned to has its OnAppearing override invoked, provided that the underlying platform isn't Android.
NOTE: it seems to depend on the API version of Android. I just tested it on API 30, and Android did fire OnAppearing again, when modal page was popped.
Instead of code in OnAppearing, I would solve it like this:
In App.xaml.cs, instead of:
MainPage = new MainPage();
do:
if (!App.IsUserLoggedIn)
MainPage = new LoginPage();
else
MainPage = new MainPage();
Then when LoginPage is done, instead of pop modal, do:
Application.Current.MainPage = new MainPage();
NOTE: Adapt as needed, if these are pages inside NavigationPage or AppShell.

How do I show a second page that I have created in XAML - UWP C#

I have made a program in WPF previously and am trying to transcirpt it into UWP. However I have come across a barrier.
In WPF you can easily create a new instance of a window and .Show that window
For example:
public static SecondGUI_Window secondGUI = new SecondGUI_Window();
secondGUI.Show();
However in UWP I am still confused as how to create a new window. I have tried doing it the same way as in WPF however it doesn't seem to work. I have also viewed and tried a couple of other answers from other stack overflow's
Second Window - XAML page (UWP app)
To no avail have I been able to get it working yet.
The main reason I want to have the second screen is so that I can display data on another screen.
For example the second window can be moved to another screen if the user has two screens.
I would like to keep as much of the usability/flexibility from WPF instancing as possible. For example being able to access the public variables in the window.
When I try and use the code from the example above it gives me an 'await' error.
Image showing error from visual studio
If you need any extra information please ask and I will try my best to provide any information requested.
Any and every help is greatly appreciated.
From the link provided by quaabaam I have managed to get it working.
From the code in the link I used in my question and some help from you guys I've now managed to have a second window running at the same time.
private async void Page_Loaded(object sender, RoutedEventArgs e)
{
CoreApplicationView newView = CoreApplication.CreateNewView();
int newViewId = 0;
await newView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
Frame frame = new Frame();
frame.Navigate(typeof(DisplayWindow), null);
Window.Current.Content = frame;
Window.Current.Activate();
newViewId = ApplicationView.GetForCurrentView().Id;
});
bool viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(newViewId);
}
Making sure I had the async in the method call, the program now opens a second window.
Now I need to make sure I can get the second window working how I want it to without any issues...

Xamarin Forms Messaging Center Not Working

I am new to C# and Xamarin Forms and am trying to implement Messaging Center in my project. I am trying to push a modal page and then send data from the modal back to the original page. However, it isn't quite working as I expected.
Here is the code from the main page:
MessagingCenter.Subscribe<Info, string[]>(this, "nameUpdate", (sender2, name) =>
{
dataName.Text = name[0];
});
await Navigation.PushModalAsync(new Info(dataName.Text));
MessagingCenter.Unsubscribe<Info, string[]>(this, "nameUpdate");
And here is the code to execute when a button is pressed on the modal page, where message is a string[]:
await Navigation.PopModalAsync();
MessagingCenter.Send<Info, string[]>(this, "nameUpdate", message);
MyPage is the name of the original page, and Info is the name of the page that is being called as a modal. I am not getting any errors, just the statements in the subscribe block are not executing.
Thank you in advance.
Try to remove unsubscribe and swap the order of these two:
await Navigation.PopModalAsync();
MessagingCenter.Send<Info, string[]>(this, "nameUpdate", message);
It seems the unsubscribe happens before the send.

How can a universal windows app have multiple independent windows (Like Microsoft's app “Photos”)?

I do know how to open additional windows using TryShowAsStandaloneAsync. However, if the original window is closed - TryShowAsStandaloneAsync fails (Why?). And I don't know how to "revive" it (-the original window).
But "Photos" seems to work fine just like a desktop application. How does it do that? (I'd like to emulate that.) One can open a window with an image, open another one, close the first, and still be able to open more windows.
Any way would be fine - some way to launch windows without the main window showing, or some way of reviving the main window after it's closed (in order for it to be the new window that has to be opened), or some other way.
Have a look at the MultipleViews sample app. This app does have the problem you're describing.
Each view that you create will have their own UI Thread, and therefore dispatcher.
The key to this app is that TryShowAsStandaloneAsync is called from the dispatcher of the currently active window.
In the sample's OnLaunched event, the code looks for a reference to the currently open view, using the view id from the launch arguments. It then uses the dispatcher associated with that view to call UI code, using Dispatcher.RunAsync, on that view's UI thread. You should use that thread of the open window to call TryShowAsStandaloneAsync to launch your new main view. You can then call Window.Activate using the new main view's dispatcher.
Answering why TryShowAsStandaloneAsync fails once you have closed the main window:
I think TryShowAsStandaloneAsync tries to use the main view as the anchor view (ie, a window to place the new window relative to).
Once you close the main window TryShowAsStandaloneAsync fails because it has no anchor view.
The workaround is to specify an anchorViewId of a view that is open (one of the new windows you opened prior to closing the main window), via an overload of TryShowAsStandaloneAsync:
await ApplicationViewSwitcher.TryShowAsStandaloneAsync(
viewIdToShow, // Id of a new view, or of your hidden main view
ViewSizePreference.Default,
anchorViewId, // Id of one of your visible windows
ViewSizePreference.Default);
From this answer.
I'm not sure if you're using Dispatcher.RunAsync to create the view, i.e:
async private void Button_Click(object sender, RoutedEventArgs e)
{
CoreApplicationView newView = CoreApplication.CreateNewView();
int newViewId = 0;
await newView.Dispatcher.RunAsync(CoreDispatcherPriority.High, () =>
{
var frame = new Frame();
frame.Navigate(typeof(MainPage), newViewId);
Window.Current.Content = frame;
// In Windows 10 UWP we need to activate our view first.
// Let's do it now so that we can use TryShow...() and SwitchAsync().
Window.Current.Activate();
newViewId = ApplicationView.GetForCurrentView().Id;
});
bool viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(newViewId);
}
for more info, please refer to : https://daxsnippets.wordpress.com/2015/07/09/windows-10-create-views/

Override BackKeyPress in a classlibrary, is that possible on WP8?

I pass a PhoneApplicationPage instance to a classlibrary, and popup an usercontrol in this classlibrary, when I press back button, the whole application exit. Yesterday I sovled the problem in an application, but I cannot use the method in this classlibrary case.
I tried to subscribe to the event(BackKeyPress), but VS2012 says "parent_BackKeyPress" "System.EventHandler" override and delegate cannot match. I checked, they match.
PhoneApplicationPage mContext=...;
mContext.BackKeyPress += new EventHandler(parent_BackKeyPress);
void parent_BackKeyPress(CancelEventArgs e)
{
ppChangePIN.IsOpen = false;
Application.Current.RootVisual.Visibility = Visibility.Visible;
}
anything incorrect here? plus, can I use navigationservice in classlibrary? I did this before to navigate to a page created in the classlibrary like below, well it ends up crashing. Some say can't use pages in classlibrary, instead we should use Popup(usercontrol).
mContext.NavigationService.Navigate(new Uri("/ChangePINPage.xaml", UriKind.Relative));
I have successfully done just that:
// or some other method of accessing the current page
// - but via Application, to which you have access also in class library
var currentPage = (PhoneApplicationPage)((PhoneApplicationFrame)Application.Current.RootVisual).Content;
currentPage.BackKeyPress += (sender, args) =>
{
// Display dialog or something, and when you decide not to perform back navigation:
args.Cancel = true;
};
Of course you have to make sure that this code is executed if and only if the CurrentPage is the main page.
I also use Pages in class library. You can use NavigationService in class library: you can get it for example from current page obtained as above (currentPage.NavigationService). Or you could use the Navigate method of PhoneApplicationFrame:
((PhoneApplicationFrame)Application.Current.RootVisual)
.Navigate(
new Uri(
"/ClassLibraryName;component/SamplePage.xaml",
UriKind.Relative));
As the short Uris like "/SamplePage.xaml" will work in Application Project, to navigate to page in class library you have to give full location: "/ClassLibraryName;component/SamplePage.xaml".
But note, that if the application chooses to display message box to stop from exiting, it will not pass certification, as (from Technical certification requirements for Windows Phone):
5.2.4.2 – Back button: first screen
Pressing the Back button from the first screen of an app must close the app.

Categories