.Net MAUI Shell navigating to the previous page is not working - maui

I have a .Net MAUI app that uses Shell TabBar for navigating. Besides navigating to various pages, some tabs should just execute some code without showing any content. As TabBar does not provide such a functionality, I used OnAppearing() method of a dummy empty page, and after my code call
Shell.Current.GoToAsync("..");
to return to the previous page. But for some reason, this does not work, and the empty page is still displayed. If I use some actual page, e.g.
Shell.Current.GoToAsync(nameof("SomePage"));
the navigation works as expected, and SomePage is displayed.
Why doesn't ".." work for me?
Here is the code I use:
public class Page1 : ContentPage
{
protected override void OnAppearing()
{
// Some code I need to execute
Shell.Current.GoToAsync("..");
}
}

Related

NavigationPage won't reappear

(Sorry if this question is stupid or has already been asked before)
I'm pretty new to .NET MAUI and I'm trying to build an app and I have this code:
private async void BtnOptionsClicked(object sender, EventArgs e)
{
OptionsPage optPage = new();
NavigationPage navPage = new(optPage)
{
Title = optPage.Title
};
navPage.ToolbarItems.Add(new ToolbarItem("BackButtonPlaceholder", "", async () =>
{
System.Diagnostics.Debug.WriteLine("Back button pressed");
await Navigation.PopAsync();
}));
await Navigation.PushAsync(navPage);
}
I'm trying to add a back button for a specific page, not the MainPage
The problem is that the NavigationPage appears the first time and works, but the second time around it just doesn't show up, only the OptionsPage does
Btw it works fine on Android, just not Windows (I can't test on other platforms)
I tried using RemovePage instead of PopAsync and I tried adding the ToolbarItem in the OptionsPage class, nothing I tried works...
You are mixing Shell and NavigationPage, by default a .NET MAUI project is created with a Shell.
NavigationPage is hierarchicall (you push / pop pages on a stack), it's simpler to use and is more flexible but you have manage everything yourself (like menus for exemple).
Shell is URI-based navigation (work the same as a website pages with urls like "/users/1/profile"), it comes with pre designed menu (tabs and flyout) and make it possible to navigate to absolute URL (which is not easy with NavigationPage). It is "replacing" NavigationPage since it cover a lot of use cases and remove a lot of boilerplate code related to navigation (that's why it's the default).
Since Shell is based on NavigationPage using the NavigationPage methods with Shell wont do any error, you should not mix them though (they are not meant to be used together).
If you want to use NavigationPage you should modify ./App.xaml.cs:
public partial class App : Application
{
public App()
{
InitializeComponent();
// Replace :
// MainPage = new AppShell();
// By this :
MainPage = new NavigationPage(new MainPage());
}
}
Now you can use Navigation.PushAsync(page);, the page object should inherit ContentPage and not another NavigationPage.
If you want to keep Shell read this and use await Shell.Current.GoToAsync("../../route"); to navigate between page.

Eclipse RCP: Get notified when IWorkbenchPreferencePage is left

I have implemented two custom IWorkbenchPreferencePage's and they are working as expected. Basically Page1 shows different information based on the selections made in Page2. The problem is that I have to close (explicitly save) the preference dialog to see the changes of Page2 reflect in Page1.
Now I was wondering if there is some kind of mechanism that would allow me to do something (In my case save information on the open preference page) once a IWorkbenchPreferencePage gets left.
You can override the okToLeave method which is called when a different page is selected.
The default implementation of this in PreferencePage is:
#Override
public boolean okToLeave() {
return isValid();
}
You can also use the
public void setVisible(boolean visible)
method which is called when the page is made visible and when it is hidden (be sure to call super.setVisible in your override).

Handle button click in Xamarin Forms Android to Navigate to new page

I am trying a simple Android app using Xamarin Forms with C# for the coding. In my Main.axml there's a button, on clicking which I'd like to go to a new page, say XInfo.axml.
Now this is my MainActivity.cs:
using System;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Xamarin.Forms;
namespace AlberoPizza
{
[Activity(Label = "Albero Pizza", MainLauncher = true, Icon="#drawable/icon")]
public class MainActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
//// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
// Get our button from the layout resource,
// and attach an event to it
Button btn = FindViewById<Button>(Resource.Id.MyButton);
btn.Clicked += (object sender, EventArgs e) => {
};
}
}
}
Now, I am finding it difficult to structure code inside my Lambda which would handle the navigation to the page, whose name I mentioned. There is no Navigation Bar and there cannot be any navigation bar. Also, for the existing code block, I am getting this error, which is quite weird to me:
Error CS0311: The type 'Xamarin.Forms.Button' cannot be used as type parameter 'T' in the generic type or method 'Android.App.Activity.FindViewById(int)'. There is no implicit reference conversion from 'Xamarin.Forms.Button' to 'Android.Views.View'. (CS0311) (AlberoPizza)
I thought this is how we usually find controls in Android app Xamarin. Can you help me complete the code for this? I'm sure it's a pretty basic type of scenario. There is this persistent error on the one hand and the code to navigate to XInfo.axml on the other. I've tried stuff like Activator.CreateInstance, the PushAsync, etc. inside the lambda, but more errors show up and entire thing becomes more and more complicated.

Wicket AjaxLink javascript handler shows strange behaviour

I have a ListView that displays a list of Panels, one below the other. Every panel features a button (implemented via AjaxLink) that closes the panel and removes it from the list.
This is how the ListView is initalized and how the panels are created:
panelsList = new ArrayList<MyPanel>();
pnlContainer = new WebMarkupContainer("pnlContainer");
ListView<MyPanel> pnlItems = new ListView<MyPanel>("pnlItems", panelsList) {
#Override
protected void populateItem(final ListItem<MyPanel> item) {
item.add(item.getModelObject());
item.add(new AjaxLink<Void>("pnlClose") {
#Override
public void onClick(AjaxRequestTarget target) {
panelsList.remove(item.getModelObject());
target.add(pnlContainer); // repaint panel container
}
});
}
};
pnlContainer.setOutputMarkupId(true);
pnlContainer.add(pnlItems);
add(pnlContainer);
This works so far - the actions that trigger adding new panels (usually also AjaxLinks) do what they should and the new panel is added and displayed correctly. But I have problems getting the close button to fully work.
Please see the following steps:
1) I start the server and navigate to the main page. The ListView is initially populated with one panel.
Close-button-code of this panel:
<a wicket:id="pnlClose" id="pnlClose7" href="javascript:;">Close</a>
Searching the page code for pnlClose7 finds the following javascript code that makes the button work as expected:
Wicket.Ajax.ajax({"u":"./?0-1.IBehaviorListener.0-pnlContainer-pnlItems-0-pnlClose","e":"click","c":"pnlClose7"});;
Note: I do not press the button now, if i would, it would work as expected (thoroughly tested).
2) I trigger an action that opens a second panel. The panel is displayed below the first one as expected.
Close-button of the first panel:
<a wicket:id="pnlClose" id="pnlClosef" href="javascript:;">X</i></a>
Close-button of the second panel:
<a wicket:id="pnlClose" id="pnlClose10" href="javascript:;">X</i></a>
But now, neither searching for pnlClosef nor pnlClose10 finds some javascript code. The buttons (both!) do not work. I can still find the javascript code for pnlClose7.
3) I reload the page via pressing F5.
The button IDs change to pnlClose1a and pnlClose1b. Both IDs have javascript counterparts and work.
4) I press the first button (upper panel, ID pnlClose1a). The panel is closed as expected.
The remaining button's ID changes to pnlClose1c, again without a javascript counterpart. Javascript code for pnlClose1a and pnlClose1b is still present.
To make a long story short, the javascript handlers for my AjaxLinks seem to have shyness issues and only appear after I press F5 or reload the whole page in any other manner. I guess thats because repainting the pnlContainer changes the IDs of the current panels - but why is the linked javascript not updated at the same time? Is there anything I can change in my code to update the whole page without completely reloading it?
Wierd thing is that I am pretty sure this worked before... But I checked the whole class history and can't find any major change that would have triggered that. The ListView-code is mainly static since I added it.
I was had similiar problem. if you have any hardcoded javascript code in your page or panels html file (using <script> tag) remove it and set that js code in renderHead of your panel.

How to show a WinJS AppBar when a page fragment loads?

I'd like to show the AppBar when a page fragment loads, but this code running in the ready function isn't working as expected:
function ready(element, options) {
var appBar = document.getElementById("appBar").winControl;
appBar.disabled = false;
appBar.show();
}
How do I show the AppBar when the page fragment loads?
Assuming you are creating the appbar correctly in the HTML file.
Then, in the ready method, you should first call
WinJS.UI.processAll(elements)
.then(function () {
var appbar = document.getElementById("appBar");
if (appbar) {
appbar.winControl.show();
}
});
According to MSDN documentation, processAll function "applies declarative control binding to all elements, starting at the specified root element." (i.e. turning all the html element into WinJS controls)
I've tried the following piece of code:
document.getElementById("appBar").winControl.show()
And it works as expected(app bar is shown on page load).
The same way also used at the msdn sample:
App bar sample
It seems that you have another problem(invalid controls on app bar or something else).
Could you please provide more details or even app sample?
If you get null error call WinJS.UI.processAll() in your initialization code.
WinJS.UI.processAll();
appBar.winControl.show();
HTML
<div id="appBar" data-win-control="WinJS.UI.AppBar" data-win-options="{placement:'bottom'}">