How do you close a view from another view in .net maui? - c#

I am trying to implement a loading/is busy logic in my app. When the item is selected from a collection view it shows a popup of a activity indicator which works fine. But, I am unable to close the popup once the other view loads. I have tried calling Close() but that doesnt do anything. So pretty much just trying to figure out the best way to show a activity indicator then close it once the process is done.
async void ItemSelected(object sender, SelectionChangedEventArgs e)
{
var popup = new LoadingPopup();
this.ShowPopup(popup);
var item = e.CurrentSelection.FirstOrDefault();
if (item != null)
{
await Navigation.PushAsync(new YearPage(item) {BindingContext = item });
//await Application.Current.MainPage.Navigation.PushAsync(new YearPage
//{
// BindingContext = item
//});
}
}
Calling close on the popup from a different view page(as the method doing the work is on a different page and I want to close the popup once it is done) doesnt work.

you need to pass a reference to the popup to the 2nd page
var popup = new LoadingPopup();
this.ShowPopup(popup);
var item = e.CurrentSelection.FirstOrDefault();
if (item != null)
{
await Navigation.PushAsync(new YearPage(item, popup) {BindingContext = item });
then you would have to modify the YearPage constructor to accept that 2nd parameter
then you would have a public method on LoadingPopup to dismiss via the Close() method

Related

Page navigation event

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();
}

Monotouch interactivePopGestureRecognizer and Navigation.popasync() blank view

I just noticed a odd behavior when using the interactivePopGestureRecognizer to go back in my app.
Case scenario:
1) User Drags view from left to right he goes back one view "interactivePopGestureRecognizer".
2) User swipes up or down "await Navigation.PopAsync(false);" is called and user goes back one view.
3) if User does action "1" and then calls a new view and tries to go-back using action 2 a blank view is displayed.
This error is only appearing if the user uses action 1 and then tries to use action 2; app works fine if action 1 is never used or if only action 1 is used, no both.
I am using Xamarin.Forms and I tried to used "interactivePopGestureRecognizer.enabled = false", but I get an error every-time I tried. is there a difference between the two back navigations?
-------------UPDATE----------
After reading a lot and looking in the internet I found out that ~interactivePopGestureRecognizer.enabled = false only works if you use it inside the ~ViewWillAppear I created a custom renderer that applies this to every tableView in my app. I would still want to figure out why is the back swipe acting this way.
----UPDATE 2---
Just pressing the back button and then trying to call navigation.popasync is giving me a blank page too. this seems to be an error between Xamarin.Navigation and the iOS back function.
Page:
MessagingCenter.Subscribe<string>(this, "UpSwipe", async (sender) =>
{
try
{
//await Navigation.PopAsync(false);
Navigation.RemovePage(this);
}
catch (Exception e)
{
await DisplayAlert("IsLoading", e.ToString(), "OK");
}
});
MessagingCenter.Subscribe<string>(this, "DownSwipe", async (sender) =>
{
try
{
//await Navigation.PopAsync(false);
Navigation.RemovePage(this);
}
catch (Exception e)
{
await DisplayAlert("IsLoading", e.ToString(), "OK");
}
});
Renderer:
private void UpdateUp()
{
// Insert view of DetailLeft element into subview
// Add button to open Detail to parent navbar, if not yet there
// Add gesture recognizer for left swipe
//Console.WriteLine ("Left swipe");
if (!buttons[2].Selected && !buttons[1].Selected)
{
MessagingCenter.Send("Swiped Up", "UpSwipe");
}
}
private void UpdateDown()
{
// Insert view of DetailLeft element into subview
// Add button to open Detail to parent navbar, if not yet there
// Add gesture recognizer for left swipe
//Console.WriteLine ("Left swipe");
if (!buttons[2].Selected && !buttons[1].Selected)
{
MessagingCenter.Send("Swiped Down", "DownSwipe");
}
}
After hours of debugging I fixed my issue by adding a return statement inside my renderer. I was checking and adding some gestureRecognizers in my renderer so a return was not needed until this bug came out.
protected override void OnElementChanged (ElementChangedEventArgs<LRMasterDetailPage> e)
{
base.OnElementChanged (e);
if (e.OldElement != null)
{
return;
}
}

Using C# & Xamarin Forms - How can I close one modal without setting of chain of closures

In one stage of my app (Android & iOS are the ones we care about) we've got three pages which take in details and then open a webView for the user to input their card details to take a payment - this can't be done in the app due to Apple's guidelines.
I need to format the navigation in a way that when the user has finished in the webView it closes and then closes the 3 previous modals to get back to the original page. I've got it all working with the Appearing event so each page just closes itself:
this.Appearing += async (s, e) =>
{
await Navigation.PopModalAsync();
};
The issue I'm now having is that when the user presses the back button on the phone, it closes all of the pages that they've been through already & back to the original. I thought about implementing a custom nav bar and disabling the back button on the hardware but this would cause the same problem with the Appearing event.
Is there any easy way to solve this?
EDIT: Relevant code;
async void OnButtonClicked(object sender, EventArgs eventArgs)
{
if (IsConnected)
{
ActivityIndicator.IsVisible = true;
var button = (Button) sender;
button .IsEnabled = false;
await Navigation.PushModalAsync(new Page());
this.Appearing += (s, e) =>
{
ActivityIndicator.IsVisible = false;
button.IsEnabled = true;
RefreshPage();
};
}
else
{
NoInternetLabel.IsVisible = true;
}
}
Use this:
YourButton.Clicked += OpenPage;
OpenPage looks like this:
async public void OpenPage(object sender, EventArgs args)
{
await Navigation.PushAsync(new PageToShow());
}
You don't have to do anything to handle the PageToShow() closing, that happens by itself when the user presses the back button.
Managed to solve this by using Actions. In each new Page() we passed up an async method to close it once the one after had completed;
var nextPage = new Page(async () =>
{
await Navigation.PopModalAsync();
_completedSuccessfully();
});
await Navigation.PushModalAsync(nextPage);
And in the new page class;
private readonly Action _completedSuccessfully;
public Page(Action completedSuccessfully)
{
_completedSuccessfully = completedSuccessfully;
}
This meant that when the webView closed it called the completedSuccessfully() action and then chained all of them to the original page.

How to set a "First-Launch-View" in C#

I searched everywhere, but i can't find a tutorial for my problem. I want to set an page to be shown, when the App is launched for the first time. something like th:
First launch:
Greeting.xaml>Setting.xaml>MainPage.xaml
Regular launch goes directly to MainPage.
how can i do this?
I didn't mean a Splashscreen, I mean a page, which is shown only the first time you launch the App, something like a little tutorial.
Your typical template-generated App.xaml.cs has something like this in its OnLaunched method:
if (rootFrame.Content == null)
{
rootFrame.Navigate(typeof(MainPage), e.Arguments);
}
This is where you navigate to your first page. To special-case a first run, do something like this instead:
if (rootFrame.Content == null)
{
IPropertySet roamingProperties = ApplicationData.Current.RoamingSettings.Values;
if (roamingProperties.ContainsKey("HasBeenHereBefore"))
{
// The normal case
rootFrame.Navigate(typeof(MainPage), e.Arguments);
}
else
{
// The first-time case
rootFrame.Navigate(typeof(GreetingsPage), e.Arguments);
roamingProperties["HasBeenHereBefore"] = bool.TrueString; // Doesn't really matter what
}
}
The greetings page should then navigate to your settings page, which should navigate to your main page.
And by using the roaming settings, the user won't see the first-time screen when she logs in to a different machine.
You can set the "first" page within the App.xaml.cs. Search for the OnLaunched void and change rootFrame.Navigate(typeof(MainPage)); to rootFrame.Navigate(typeof(Greeting)); or whtatever you like to call it.
The next step would be to check if the app launches for the first time. You can set an app setting to do that.
1. create the OnnavigatedTo void for your Greeting.xaml (just type "protected override void onna", IntelliSense will suggest it to you) and make is asynchron by inserting "async" after "protected", 2. use this code:
if (ApplicationData.Current.LocalSettings.Values.ContainsKey("isFirstLaunch"))
{
// if that's the first launch, stay, otherwise navigate to Settings.xaml
if (!(bool)ApplicationData.Current.LocalSettings.Values["isFirstLaunch"])
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => Frame.Navigate(typeof(Settings)));
}
}
else
{
ApplicationData.Current.LocalSettings.Values["isFirstLaunch"] = false;
}
I haven't tested the code but it should work. If it doesn't, just ask me.
Edit: here's a much better solution :D https://stackoverflow.com/a/35176403/3146261
I just wanted a Disclaimer to be accepted via a MessageBox
IPropertySet roamingProperties = ApplicationData.Current.RoamingSettings.Values;
if (!roamingProperties.ContainsKey("DisclaimerAccepted"))
{
var dialog = new MessageDialog(strings.Disclaimer);
dialog.Title = "Disclaimer";
dialog.Commands.Clear();
dialog.Commands.Add(new UICommand { Label = "Accept", Id = 0 });
dialog.Commands.Add(new UICommand { Label = "Decline", Id = 1 });
var result = await dialog.ShowAsync();
if ((int)result.Id == 1)
Application.Current.Exit();
roamingProperties["DisclaimerAccepted"] = bool.TrueString;
}
I placed it in App.xaml.cs inside of:
if (e.PrelaunchActivated == false)
{
<Inside here>
if (rootFrame.Content == null)
{
}

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