Multiple NavigationPages Outside of MainPage - maui

We are mostly a WPF shop currently and are exploring MAUI development for future projects. We have a need to track three separate layers of content (in addition to any necessary modal content), which each navigate and may all be visible on the screen at once.
I am attempting to work through various use-cases in a test app, and am separating cases in a TabBar. I had thought to use three NavigationPages in the VM of one tab and navigate each independently, but I am stumbling over getting even one to work, let alone three.
I have tried several different approaches, including ContentPresenter and ContentView, but here is the core of my most recent approach:
public NavTestVM()
{
NavPage = new NavigationPage(new NavRoot());
}
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiAndUnitTest.Views.NavTest"
x:DataType="viewModels:NavTestVM">
<TemplatedPage ControlTemplate="{Binding NavPage.CurrentPage}" HeightRequest="400" WidthRequest="600"/>
</ContentPage>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiAndUnitTest.Views.NavTestViews.NavRoot"
BackgroundColor="Coral">
</ContentPage>
The NavRoot page (the root page in NavPage) does not appear in the tab. If, in App.xaml.cs, I replace
MainPage = new AppShell();
with
MainPage = new NavigationPage(new NavRoot());
I get a page full of Coral-y goodness on startup. What am I missing to get current NavigationPage content to display, outside of App.xaml.cs.MainPage?
Assuming I can get this working, I would then expect I can just repeat the approach twice more for the other layers and call it good.

Related

dotnet maui how to hide the back button on desktop?

I'm trying to hide the backbutton shown in the image on desktop, but no matter what I tried, then it keept showing up.
I have tried
<Shell.BackButtonBehavior>
<BackButtonBehavior IsVisible="False" IsEnabled="False" />
</Shell.BackButtonBehavior>
And I have tried following this SO post Why Back Button is hidden in Maui?
My navigation is done by saying await Shell.Current.GoToAsync(new ShellNavigationState(location), false);
Am I missing something?
So everything you need to know can be found here:
https://learn.microsoft.com/en-us/dotnet/maui/user-interface/pages/navigationpage
NavigationPage.HasBackButton = true/false
Image (Proof)
https://gyazo.com/afbc744e7b6c5d1caa56960a536390c7
If this was helpful, mark this please as answer :)
This technique (the code in your question), added within the <ContentPage ... > declaration at the top of the xaml:
<Shell.BackButtonBehavior>
<BackButtonBehavior IsVisible="False" IsEnabled="False" />
</Shell.BackButtonBehavior>
seems to work when using the Shell to activate pages in C# codebehind (often in the BindingSource e.g., viewmodel):
await Shell.Current.GoToAsync($"{nameof(MyContentPage)}");
Adding this within the <ContentPage ...> declaration at the top of the xaml:
NavigationPage.HasBackButton="false"
seems to be applicable when using the push/pop within a NavigationPage:
await Navigation.PushAsync(new DetailsPage());
I don't use the Navigation.PushAsync. My app requires very specific navigation based on current data state, so a stack doesn't work for me.
I have verified setting the Shell.BackButtonBehavior (in the very code you provided) works in my case because I am activating pages via
await Shell.Current.GoToAsync
To enable/disable something you can use OnPlatform or OnIdiom
Exemple :
NavigationPage.HasBackButton="{OnIdiom Default='True', Desktop='False'}"

Shared TitleView in Xamarin.Forms AppShell

Is there a way to implement a shared TitleView component in Xamarin.Forms AppShell? I've tried a couple of approaches but it's not working as I intended.
What I'm trying to achieve is something like the following:
App Shell with a few tabs and a common Shell TitleView
The titleView is just a ContentView (let's call it Exposure) with a label to display the result of a calculation and a refresh button to fetch data and recalculate
Changing Tab shouldn't affect the state of the TitleView
What I've tried:
Initialize one instance of the Exposure component (View and ViewModel) and configure it on the DI framework to use that instance only (singleton).
When the Pages are initialized I get the single instance of the Exposure component and assign it to the Shell.TitleView property.
By doing this I was hoping that the Exposure state would be consistent across the tabs (single instance after all...), but what happens is that when I hit the refresh button it only refreshes the calculation on the current tab Exposure component, changing tab will present me with the Exposure component with old state. I'm surprised this is not supported out of the box (configure titleView at Shell level) but I might be missing something.
Might not be relevant but I'm using ReactiveUI (MVVM) and Splat (dependency injection)
The next thing I'm willing to try is to trigger a refresh when each page re-appears but that feels dodgy.
You can create a base ContentPage and set the style of TitleView of it .
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="xxx.BaseContentPage">
<NavigationPage.TitleView>
<StackLayout>
//...
</StackLayout>
</NavigationPage.TitleView>
<ContentPage.Content>
<StackLayout>
//...
</StackLayout>
</ContentPage.Content>
</ContentPage>

how to create a master page or a page which is in common to all the views using gwt mvp

Hi I am new to GWT MVP pattern. I am from asp.net background and currently I am working on GWT and I am asked to create a Master page which has the menu items which should be in common to all the views. Initially I created a sample mvp project using https://developers.google.com/web-toolkit/articles/mvp-architecture-2 and in that there is navigation from one view to another. How do I maintain one view constant and keep changing the other views depending on what menu item we click. Please help
The article you mentioned is from before MVP support added in GWT. It's good at explaining the concept, but the actual implementation is less useful. To continue take a look at the GWT documentation about activities: https://developers.google.com/web-toolkit/doc/latest/DevGuideMvpActivitiesAndPlaces . There you will also find the solution for your problem. In brief, take a look at the ActivityManager. This manages all activities. On the activity manager you set one widget that will be static for all activities. This widget must have a method setWidget (actually it must implement AcceptsOneWidget). In each of your activity implementations you get this widget via the start method. And by calling setWidget with the specific view for that activity in the start method you set the activity specific view. This is all described very briefly, but you should get the concept if you read the mentioned documentation.
If you are working with UiBinder, your ui.xml file should be like this,
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui">
<ui:style>
</ui:style>
<g:DockLayoutPanel unit="EM">
<g:north size="4">
//Add Logo, menus or what you want to be displayed for all the pages
</g:north>
<g:center>
//Add code for your desired UI. In java code you change the UI by this "flowpanel"
For eg: <g:FlowPanel ui:field="flowpanel" />
</g:center>
</g:DockLayoutPanel>
Then everytime you can clear and add the widgets to be displayed in the view in the <g:center> using your java code like this flowpanel.clear();
flowpanel.add(anyWidget you need).
So <g:north> will be static view and <g:center> will be dynamic view. Now you will get the page as you desired. Since you can change everytime your view on <g:center> only.
Like this you can add <g:east>, <g:west> and g:south> if required.
If you are not working with UiBinder then do everything in your java code as follows,
final DockLayoutPanel dockLayoutPanel = new DockLayoutPanel(Style.Unit.EM);
dockLayoutPanel.addNorth(any widget you need, "4"); //NorthPanel
dockLayoutPanel.add(any widget you need); //CenterPanel
Where "4" is the size of the panel, you can change it.
Like this dockLayoutPanel.addWest(any widget you need, "4"); //WestPanel
dockLayoutPanel.addEast(any widget you need, "4");//EastPanel
dockLayoutPanel.addSouth(any widget you need, "4"); //SouthPanel
I hope you got idea now.
You divide your screen into two or more areas, and assign dedicated ActivityMapper and ActivityManager to each zone. For example, one zone can be "menu" with MenuActivityManager, and the other zone "body" with BodyActivityManager.
Here is a good explanation:
http://blog.ltgt.net/gwt-21-activities-nesting-yagni/
Note that there are both pros and cons for using this method. Browsers take milliseconds to render standard html. It may be easier to create a widget mainMenu and include it (best of all, using UiBinder) into every view, rather than deal with two activity managers.

How to manage the creation of instances when navigating

I am programming WP7 application adhering the MVVM pattern.
I have ViewModelLocator which ensures that each instance of ViewModel is only one. These ViewModels are created when application is launched. ViewModels communicating with each other using messages. I use messages for navigatig to next Page (For this I am using NavigationService.Navigate(), which is Raised from MainPage CodeBehind - it is the only functionality that is in CodeBehind ). View and ViewModels are connected together by setting the DataContext in the Page to ViewModelLocator.
Everythig works at first sight.
But during each navigation, there is created new Page instance, which is connected to the ViewModel from ViewModelLocator(which is designed for it). The result is that: when a user often switches between pages, there are multiple instances of a page connected to one ViewModel. Of course, there is visible only one page at one point.
Very simple solution could be setting NavigationCache, but it is readonly in WP7.
I am looking for solution of unwanted behavior.
Every time you Navigate somewhere a new instance is created for that page.
You could avoid this by using NavigationService.GoBack(); where ever you can.
You should also unregister from every event when navigating away from the page, so that way the garbage collector can clear out that page.
I hope this helps.
You may try to declare an instance of your ViewModel at App.xaml.cs, such as,
private static YourViewModel viewModel = null;
public static YourViewModel ViewModel
{
get
{
// Delay creation of the view model until necessary
if (viewModel == null)
viewModel = ViewModelLocator.MainStatic;
return viewModel;
}
}
Then from the page you will navigate to, you can reference it as App.ViewModel.
If your page is in different assembly form your main application, you could declare following in your App.xaml,
<vm:ViewModelLocator x:Key="VMLocator" />
Where vm referencing to your main app, then you can use is as following,
((ViewModelLocator)Application.Current.Resources["VMLocator"]).YourViewModel;
Hope it would help.

Nvigation within a GWT application

I intend to build a web application where users can enter their time every week and have been struggling to get my head around the concept of a single page in GWT that gets repainted with data depending on the user actions. After researching a lot on this site and google, I found one link that I would like to emulate but dont know how to go about doing it in GWT. Although their source code is available, I dont think it is full and complete. I got some idea from this link - Multiple pages tutorial in Google Web Toolkit (GWT) but again dont know how to implement it into a working version. One small working sample would be great to help me understand and get started.
Could anyone please guide me as to how to achieve the look and feel of the screen with the link below and how the content can be repainted with data from the server ? Would I need to put all the logic in one EntryPoint class ? I would like to have the hyperlinks in the left navigation panel and show the content in the right panel. I seem to be completely lost after a few hours of research.
http://gwt.google.com/samples/Showcase/Showcase.html#!CwHyperlink
Thanks a lot for your help.
Regards,
Sonu.
A single page application layout is actually quite easy to achieve.
The first thing you do is define the general layout, using GWTs layout panels. For your layout, I'd suggest using a DockLayoutPanel.
Content content = new Content();
Button switchContent = new Button(content);
Navigation navigation = new Navigation();
navigation.add(switchContent);
DockLayoutPanel pageLayout = new DockLayoutPanel(Unit.EM);
p.addWest(new HTML(navigation), 7.5);
p.add(new HTML(content));
Here, the width of the navigation panel will be fixed, whereas the content will take the remaining space. You have to pass a reference of the button (or some other widget) which does the switch of the content area, add the button to the navigation area, and so on.
Put this into a class, e.g. called MasterPageFactory:
public class MasterPageFactory {
private MasterPageFactory() {}
public static MasterPage newInstance() {
Content content = new Content();
Button switchContent = new Button(content);
Navigation navigation = new Navigation();
navigation.add(switchContent);
DockLayoutPanel masterPage = new DockLayoutPanel(Unit.EM);
masterPage.addWest(new HTML(navigation), 7.5);
masterPage.add(new HTML(content));
return masterPage;
}
}
Now, in your EntryPoint class, call the factory:
RootLayoutPanel.get().add(MasterPageFactory.newInstance());
This example should get you an idea. Other options would be using a DI framework like Guice or the Command pattern.
Your question is mixing up a couple of concepts. If you want the user to click something that looks like a link, and in reponse the application sends a request to the server and shows a page that looks different than the page they're on, and that page has fresh data that just came from the server, then you want a perfectly normal anchor or form submit button. You don't need anything special or weird from GWT.
The showcase example you referenced lets the user click something that looks like a link, and looks like it loads a new page, even to the point of letting the back button work as expected, but does not actually hit the server to get a new page or new data.