Navigation Made Easy (w/ MVVM) - MAUI TUTORIALS

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
so navigation has historically been tricky in.net desktop applications I've had trouble with it and I know all of you have had trouble with it too because some of the top videos on this channel have been about navigation in WPF applications so you have an app with multiple Pages you just want to switch Pages you want to be able to click a button and go to the next page in your application it's such a simple concept but for some reason again historically it's been tricky however in.net Maui the framework handles most of the navigation concerns for us it makes it much more pleasant to work with they also provide much more such as different shell types like you can have a tab layout by default but let's forget about all that for now let's focus on navigation the fundamentals this is where it all begins so I have a demo app set up here but I have some pages in here so we have a join page and after you join I want to show this profile page represented by the index View and then we'll have another button on the profile page to view some more profile details specifically the address so I would demo this but again navigation such a fundamental concept there's not really much to show in this app until we have navigation so navigation and ml it all begins in the app shell so if you're familiar with any web development the app shell is kind of like a router so you have string keys that map to pages so you might have a join route that maps to our join page so inside the Shell let's open this up we can have shell content and we're going to define a route we'll give this a key of join and whenever we're on the join route we want to display via a Content template the join page so that's represented by a data template and we want to point to our joint view actually is what it's called and that's something that I import from this navigation dot Pages namespace up here which is this join view right over here and by default this first shell content within the shell is the page that's going to be displayed when our application boots and there we go got the join View and in the future we'll be able to click the submit button and go to the next page so let's define the next page so we're gonna just just copy this and our next page is going to be that profile page so I have that in another namespace called profile pages and that's our index view over there and we'll Define this route as profile and then let's throw in the other route while we're here so this is also going to be a profile page and this is going to be the address View and we'll give this a route a profile address actually so I did mention that the first route in your shell or the first entry in your shell is the route you start on but what if I had this at the bottom how would I go to the join page when our application starts well we can actually configure that in our app.zamba.cs so we can override on start and when our application is starting up we're just going to navigate to the page that we want to start on so here we go we're going to do our first navigation so we can so navigation's async so let's await this we're going to take the shell and we want to grab the current shell and we want to go to a sync and then just pass in the key for our route so we want to pass in join so that's the key for this join page however this is considered a relative route so we want this to be an absolute route by specifying two slashes in front and we'll get more into absolute versus relative routing and about but basically absolute routing so this is the full route it's just join starting from the top of our route hierarchy and that's what we have laid out here so we just have this join route at the root of our shell so let's beat this up we should go to the join page when our application starts there we go all good and actually I didn't even show what it was without this with our route at the bottom of the shell but we should show up on the profile page and there we go we have this empty profile so again let's start on the join page awesome so instead of navigating on Startup next up let's navigate whenever we submit our join form so let's head over to the join view model so this binds to the Joint View and we have this submit commands that executes when we click the submit button and hey I'm using the mvvm toolkit here everyone brings up the community toolkit I tried it out I love it alright so whenever we click submit and execute this submit command we want to again just like before we're going to take our shell we're going to go to async and this time we want to go to the profile page so that's the profile route let's pass that in pretty straightforward and while we're here let's add another let's actually implement this view address command so let's grab shell current go to async paste that in and this route is called profile address so let's submit the form and we're going to go to the profile page Sweet let's click this address button and we're going to go to the profile address page and there we go that's just an empty page for now we don't have any data on here awesome this is already a huge difference over WPF where we barely even written any code and we're already navigating this is just going Splendid but as we saw our profile page was empty our address page was also empty so how can we pass data or in other words I want to pass this profile that we create on the join view model and all this profile data over to our profile page that's going to be difficult right that was always difficult in WPF mvvm applications how's it going to be a Maui well it's going to be very very easy so let's go to async Method actually has another override where we can pass in parameters look at that a dictionary of parameters so let's spin up a dictionary it's a string of I don't even know is it string of objects it is a string of object so we'll just call this parameters and initialize this dictionary so let's go over to the profile viewmodel and figure out what this view model needs so we're going to want to pass some kind of is new flag from the join V model to this index view model the profile viewmodel and we also want to pass over the created profile so let's work some magic to accomplish that so we're going to have a new parameter so that's going to be the key for our parameter and the value is going to be true and then we're also going to have a profile parameter which is going to be a new profile so I have a profile entity it's actually a record and we can pass in the name property on this view model and the address property and now we can pass these parameters when we navigate so now all this data is going to get past to our index V model but it's not quite magic so it's not going to automatically populate these properties we need to tell the viewmodel how to map the properties or the parameters that we pass to the v-model to properties so we can do that with decorators or attributes I should say at the top of our view model so these are query properties we want a map too this is new property so it is new and the query parameter that we want to map is the new parameter so this new string comes from how we identified our new parameter and then same thing for the profile parameter so let's copy this so we name this parameter key profile as we can see here and we want to map that to this profile property so profile and if you're wondering oh profile property what are you talking about this is a field again that's actually something that gets generated in the background by this observable property attribute so as you can see here it will generate the corresponding property from the field cool so let's test this out we are passing query parameters to our profile page let's see it it's going to be beautiful let's submit here we go we're passing all of our properties in this dictionary let's continue and then let me click this just to hit a breakpoint and we'll be able to see all of these properties fulfilled so our is new property true that is the parameter that we passed nice our profile property is our profile awesome passing data it's that easy so much easier I love it so this was pretty Advanced parameter passing we actually spun up a dictionary and defined objects in here but if you're not passing objects or anything Advanced as your query parameters to the next page then you don't even have to spin up a dictionary so for example let's say we want to pass the profile address to our profile address page and that profile address is just the string then we don't need a whole dictionary we can do some string interpolation here add a question mark here and after this question mark we can Define all of our query parameters so these are basic these are just string parameters so I want to set the address query parameter to my profile address and since the profile address is just a string this is easy for Maui to handle it can handle it if we wanted to pass an object here using this method it would not work I don't even think booleans work I tried booleans and I couldn't get that working can't forget if it worked for numbers or not but I know it works for Strings and anything more advanced you probably want to use the dictionary approach for passing parameters but let's test this out so let's go over to our address view model and we want to add a query parameter I already added it I guess when I was prepping the video or testing something out but let's put a breakpoint here and we should we should pass our address parameter let's try it so let's go to the address page we're going to pass our address as the address parameter continue and there we are our address pops up on the page that's good that means our data made it to the profile page and we can see it on this breakpoint there we go we got the address so just two different ways for passing parameters is one better than the other I mean I I kind of like the dictionary approach I feel like it's more explicit obviously there's support for objects and more advanced values if you take this approach but for something quick and easy nothing wrong with just passing it in Via our navigation string just understand that this approach is limited and it's only going to work with Primitives possibly only strings from what I've seen so far so these are the fundamental fundamentals we're navigating we're passing data what more could you possibly want you can actually get a lot done with just what we've learned so far but let's dig a little bit deeper let's let's try and experiment and do some more cool things so suppose when we're on the profile page we have your address and we want to go back to our profile now we haven't implemented this back button yet but let's do it so let's go to the address view model and let's take our shell current and go to async and we want to go back to the profile page and before we even testing this out you can probably already see the issue so we're going to the profile page but we don't have all of these query properties required by the profile page the address remodel doesn't receive that data so it can't pass it back to the profile page now there are ways to work around this but let's just work within our constraints right now so let's not do this let's take another approach let's take shell current navigation and let's pop async so let's pop this address page off of our navigation stack and take us back to the profile page and who knows with this approach perhaps the profile page will maintain all of its state so here we go we go to the address page we go back we're going to pop off of navigation stack can we even see the navigation stack we can not actually all right let's continue and we don't end up back on the index or the profile page and that's because we're doing absolute navigation over to the profile address page so it doesn't really have the stack in its head whenever we're doing this absolute navigation or in other words if we do absolute navigation it's going to wipe the navigation stack completely however if we use relative routing instead then it's going to maintain the navigation stack and this is where route hierarchies can come into play and help us in this situation so in other words I want to Route hierarchy on these profile Pages where slash profile shows the profile page and slash profile slash address shows our address page and with the address page being under the profile page in the route hierarchy we can use relative routing on the profile page and just go to the address Route with no slashes in front and since we're using relative routing that's not going to clear the navigation stack and we should be able to pop back to our profile page so that all makes sense hopefully we're going to see it in action but what we didn't go over is how do we Implement a route hierarchy how do we Define the address page in the hierarchy underneath of our profile page well you guessed it that's all going to be configured somewhere in the app shell who knows maybe we can just change this route to profile slash address wouldn't that be great let's try it and that's not going to work we get an exception and I don't even think we're handling exceptions in our commands so it actually crashes our application so that's not ideal we don't want to do that and in fact the only way as of now to implement some kind of Route underneath of our hierarchy is with code in the app shell.xaml.cs so in this Constructor we can take routing and we want to register a route in our app shell and in here we can define a route that represents a hierarchy so we want to have a profile slash address route and that route is going to represent our address view so quite similar to the xaml that we had where we Define a route and our view the only difference is that we're doing it in code behind so that we can leverage higher our hierarchical however however you say hierarchy routing we'll go with that there we go but maybe in the future we'll be able to just do this inside of our app shell I don't really like the idea of having routes defined in our xaml and also in RCS maybe it'd be better though choose one or the other maybe I would want to move these over to our app shell.xamer.cs2 but ideally in the future something like this would just be supported in the xaml we'll see anyways we now have our route hierarchy set up let's go let's plop down some break points and let's route let's navigate I should say all right let's go to the address page here we go relative routing boom we're there and again relative routing doesn't reset the navigation stack so since we didn't reset the navigation stack or we're using a navigation stack now Maui automatically puts this convenient back button at the top it's probably a way to disable that if you don't want it but hey I like it and we can also click this back button that we implemented I want to put a breakpoint there or we we see that's popping off of the navigation stack now let's put a breakpoint why not so back there we go pop off the navigation stuck and we are back on our profile page so relative routing essential if you want to Leverage The built-in navigation stack alright so.net Maui navigation so much easier than what we had in WPF mvvam applications I know a lot of people might be like well you should use the mvvm framework in WPF we were always telling you to and yes that is correct lots of people told me to use a framework in WPF maybe I should have looking back because I'm sure there's something out here in the WPF universe that is similar to what we have in Maui I would hope so maybe not who knows but I was always that guy using vanilla WPF mvvm I guess it's different now because all of this navigation infrastructure is part of Maui whereas with WPF you had to use some other third-party framework but anyways that's enough of that rant so Maui navigation pretty solid from what I've played with so far and I feel like this is the ideal.net Maui mvvm experience so we have the built-in Maui navigation that's pretty easy to use pretty powerful and then you pair that with the mvvm toolkit it's I really like it let's build some things let's do it so in summary we now have the power to navigate between pages in a.net application we can do basic routing with go to async we can pass parameters via a dictionary where we can pass in more advanced objects rather than Primitives we can also pass parameters without using a dictionary if we just need to pass Primitives such as strings we can define a route hierarchy and leverage of relative routing which finally allows us to leverage the navigation stack and we can pop off of the navigation stack to go back to the previous page so hopefully you can apply these Concepts in your own.net Maui application to easily navigate between pages [Music] [Music] foreign
Info
Channel: SingletonSean
Views: 2,942
Rating: undefined out of 5
Keywords: wpf, programming, visual, studio, xaml, custom, control, generic, system, line, display, timer, template, binding, c#, how, to, series, tutorial, easy, time, maintain, package, design, part, event, code, register, static, state, default, view, style, wrap, panel, stack, scroll, first, width, command, func, action, void, model, user, box, mvvm, data, error, icon, class, relay, clean, simple, sub, file, host, grid, scope, align, deploy, github, actions, release, essential, rule, logic, domain, message, notify, changed, list, dashboard, datacontext, app, tile, maui, shell
Id: Jl2xUIUsZLI
Channel Id: undefined
Length: 18min 16sec (1096 seconds)
Published: Wed Nov 15 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.