FreshMvvm - Closing the child page of a page in FreshTabbedNavigationContainer - xamarin.forms

I have set up a FreshTabbedNavigationContainer with 5 pages.
Within the 5th tabbed page which is a SettingsPage where there is a way to display and AboutPage that is displayed via the SettingsPageModel like this
public Command AboutCommand
{
get
{
return new Command(() =>
{
CoreMethods.PushPageModel<AboutPageModel>();
});
}
}
When the user navigates away by selecting another tab, this other tab is displayed correctly.
If the user selects the SettingsPage via the tab, then the child AboutPage is automatically displayed.
I want to remove AboutPage from the navigation stack when another tab page is selected.
I have tried this in the AboutPage.xaml.cs
protected override void OnDisappearing()
{
base.OnDisappearing();
((AboutPageModel)BindingContext).CoreMethods.RemoveFromNavigation();
}
This works BUT if the back button is pressed on the app when in the AboutPage then it has already been removed from the navigation stack, and the app crashes.
How can I check if a PageModel is still in the navigation stack?

I have managed to resolve the problem :)
In the App.xaml.cs file in the App constructor where I create the FreshTabbedNavigationContainer, after setting the MainPage
MainPage = tabbedNavigation;
I then add the following code
tabbedNavigation.CurrentPageChanged += (sender, e) => {
tabbedNavigation.PopToRoot();
};
It works perfectly.

Related

Rg.Plugins.Popup on device back button click in Xamarin Forms

Once the Rg.Plugin.Popup is displayed, with
PopupNavigation.Instance.PushAsync(new PopupPage());
Once its displayed, and on pressing Device Back button. screen getting hanged.
No OnBackPressed in declared in the code.
Once its displayed, and on pressing Device Back button. screen getting hanged. No OnBackPressed in declared in the code.
From this article, for Android back button to work with the plugin, you should invoke Rg.Plugins.Popup.Popup.SendBackPressed in your MainActivity in override method OnBackPressed.
public async override void OnBackPressed()
{
if (Rg.Plugins.Popup.Popup.SendBackPressed(base.OnBackPressed))
{
// Do something if there are some pages in the `PopupStack`
await PopupNavigation.Instance.PopAsync();
}
else
{
// Do something if there are not any pages in the `PopupStack`
}
}

Xamarin forms: SwipeGestureRecognizer also enable MasterDetailPage Navigation Drawer?

I have implemented the swiping feature using SwipeGestureRecognizer on my homepage. But the problem is the home page is a child of a MasterDetailPage. So when I swipe to left in the homepage, the navigation drawer is also coming to UI. I have tried like below to stop showing navigation drawer on UI when doing SwipeGestureRecognizer using MessagingCenter, but no luck!!!
On Homepage
public void Swipe(object sender, EventArgs e)
{
MessagingCenter.Send<HomePage>(this, "HomePageSwipe");
//code for swipe
}
On MasterDetailPage Constructor
MessagingCenter.Subscribe<HomePage1>(this, "HomePageSwipe", (sender) =>
{
IsPresented = false;
NavigationPage.SetHasNavigationBar(this, false);
});
Is there any way to fix this?
I believe this behavior occurs only on ios. To disable this, you need to add this to the OnAppearing() method
if (Xamarin.Forms.Device.RuntimePlatform == Xamarin.Forms.Device.iOS)
{
IsGestureEnabled = false;
}

Xamarin forms: Pop up page not closing when click device back button

I am using Rg.Plugins.Popup NuGet package for showing pop up page. When clicking the android device back button the pop-up page is not hiding, it only closes the content pages. I am working on a .Net standard project.
Versions:
Rg.Plugins.Popup - 1.1.5.180
Xamarin Forms - 3.3.0.967583
Pop-up Page Codes
protected override bool OnBackButtonPressed()
{
return base.OnBackButtonPressed();
}
protected override bool OnBackgroundClicked()
{
return base.OnBackgroundClicked();
}
BackgroundClicked closing the pop-up page, but the device back button pressed not closing the pop-up page.
For Android back button issues handle on 'OnBackPressed',
public override void OnBackPressed()
{
if (Rg.Plugins.Popup.Popup.SendBackPressed(base.OnBackPressed))
{
// Do something if there are some pages in the `PopupStack`
}
else
{
// Do something if there are not any pages in the `PopupStack`
}
}

Tabbed Page OnAppearing()

I have a Tabbed Page Xamarin Form application that I am trying to customize. I am migrating from an IOs only app to all platforms. In iOS there are a couple function that I used ViewDidDisappear(), ViewDidAppear() and ViewDidLoad();
The application today loads the tabbed page as follows:
{
Children.Add(new MyPage1());
Children.Add(new MyPage2());
Children.Add(new MyPage3());
Children.Add(new MyPage4());
}
Each of the child pages are declared as follows all inheriting from ContentPage.
class MyPage1: ContentPage
{
…
protected override void OnAppearing()
{
base.OnAppearing();
Content = SomeContentPage;
}
}
The problem that I am running into is that the OnAppearing() is called for all pages when only MyPage1 is currently displayed. I need to know when each child page is loaded.
I have read about message center but I am not sure how to implement it in this particular case. Would the message center be the best solution for this?
How do I implement a solution that will allow me to know which of the four pages is displayed?
Possible workaround would be to override OnCurrentPageChanged in your TabbedPage.
protected override void OnCurrentPageChanged()
{
base.OnCurrentPageChanged();
if ( CurrentPage is YourContentPage page)
{
page.YourCustomCode();
}
}
On the main TabbedPage, after you've added child pages, setting the CurrentPage property to null should fix the problem.

CaliburnMicro StackOverflowException when ActivateItem function is invoked

I have two VM - View (inherited from Screen) and Edit (inherited from Screen). View is used to display grid with data and Edit - add/edit new items into grid.
In my ShellViewModel I have the following code to activate View.
public void WorkstationView()
{
this.ActivateItem(ServiceLocator.Current.GetInstance<WorkstationViewModel>());
}
In WorkstationViewModel when user clicks on the Create button the following code is invoked
public void CreateAction()
{
EditableObject = new WorkstationDto();
TryClose(true);
}
And there is a listener to Deactivated event property, see code below (InitViewModels is invoked in ShellViewModel constructor).
private void InitViewModels()
{
#region Init
WorkstationViewModel = ServiceLocator.Current.GetInstance<WorkstationViewModel>();
WorkstationEditViewModel = ServiceLocator.Current.GetInstance<WorkstationEditViewModel>();
#endregion
#region Logic
WorkstationViewModel.Deactivated += (o, args) =>
{
if (WorkstationViewModel.EditableObject == null)
{
return;
}
WorkstationEditViewModel.EditableObject = WorkstationViewModel.EditableObject;
ActivateItem(WorkstationEditViewModel);
};
#endregion
}
The problem here is a StackOverflow exception when I close Edit view (see create action).
“Since the Conductor does not maintain a “screen collection,” the activation of each new item causes both the deactivation and close of the previously active item.” Caliburn.Micro documentation
If you are using Conductor<T>, then ActivateItem(WorkstationEditViewModel); inside of the Deactivated handler is implicitly re-triggering the deactivation of the previous viewmodel - giving you an infinite loop. Try changing your conductor to inherit from Conductor<IScreen>.Collection.OneActive instead. However, you will still have two deactivations: the one from the original TryClose operation, and a second one when you activate the new screen. Overriding DetermineNextItemToActivate can help you avoid that.

Resources