[MUSIC] >> Welcome back to another.NET
MAUI beginners series video. I'm James Montemagno, a Product Manager on the developer community
team here at Microsoft, and we're continuing our
journey learning.NET MAUI to build beautiful
native cross-platform desktop and mobile applications. Now, so far, we've built out
an application with XAML, an XML-based markup
for user interface, we've then extended it with MVVM and data binding to make our
application responsive. Now what we're going to do is
something very common built into every single application,
which is navigation. That's right, navigating from
page A to page B. Additionally, what's great is that we can pass
data between our pages too. Now, built into.NET MAUI are
several ways of doing navigation, specifically, we're
going to take a look at URI shell-based navigation. I talked about shell
in an earlier video giving our structure
to our application, but what's great about
shell is that it not only includes a built-in
dependency service to do constructor injection and
dependency injection but it also enables us to do
a URI-based navigation. A URI, similar to a website. You go to slash details and it
will go to the details page. You can also send query
parameters that can be simple data types or
complex objects as well. It's very easy to do with.NET MAUI
with just a few lines of code. Let's hop over to Visual
Studio 2022 and get started. So far, we started to build
our My Tasks application. Here, we have full XAML user
interface and data bindings. I can add different items inside
of here, get nice animations. I can even swipe to delete. Now, this is really great, but we want to also be able to maybe tap into an item and go to details. What we're going to do now is add
navigation into our application. Let's go ahead and do that. The
first thing here is that this is the same application that we've been building through this
entire beginner series. We have our Main Page,
we have our Image, our Entry, our Button, and our CollectionView here. We've added a SwipeView so we
can add that swipe to delete. We also have the MainViewModel, which is essentially the
code behind for that page that's doing different
observable properties that we can do data binding to. So that text property that
we see there has a data binding to this text property
right here on the Entry. Let's add another page
that we can navigate to. I'm going to go ahead and
I'm going to right-click on the MauiApp2 and say Add, New Item. When I do that I'll be brought to this screen that enables me
to select different items, and there is even a subcategory
specifically for.NET MAUI. Here we have different pages
and views and resources. I'm going to select the
ContentPage XAML for.NET MAUI, and we're going to
call this DetailPage. Now, this page is a very simple page that just
says "Welcome to.NET MAUI." There it is. Perfect. There's of course no code behind
it, just very simple. Now, the other thing
we're going to do is pair this up with a view model. I'm going to come in and say Add. I'm going to say New Item in here, and under Code, we're
going to add a class, and we're going to
say DetailViewModel. I like to name my view models
very similarly to the page, so DetailPage, DetailViewModel. I've added a new class, so
we're going to add some nice C# 10 features in here, like file scoped namespaces. We're also going to make
this a public partial class. We're going to also inherit
from our ObservableObject. That observable
object is coming from our MVVM toolkit for.NET and MVVM. That community toolkit
gives us everything we need to start doing MVVM here,
which is really great. Next up, what we need
to do is we need to associate this DetailViewModel
with our page. Inside of our
DetailPage.xaml code behind, what we're going to do
is in the constructor say DetailViewModel vm, make sure we come in and
bring in that namespace, and then we're going to
set the binding context here over to the vm. Perfect. Now, just like we did for our MainPage
and our MainViewModel, we're also going to register
those in our MAUI program. This is going to register them with our dependency service so
when we navigate to them, it automatically will associate the DetailPage with
the DetailViewModel. Now the difference here is that
before we're adding singletons, but really every single time
we navigate to a new page, we wanted to create a new page. We're going to change
this to AddTransient. Singleton you can think of it
as a global where it creates one copy of it and then it will
go ahead and keep that memory, else transient will
be created and then destroyed and a new one will
be created every single time. This is what we want to have
happen every time we navigate. Now what we're going to do
at this point is register the DetailPage with the
routing system of.MAUIShell. Here inside of our AppShell, which again if you remember in here has ShellContent of the MainPage. The MainPage has a route of
MainPage, which is very convenient. I like to name my routes the
same as the MainPage here. We're going to come in
and register this page in the code behind since it's
not part of the shell. If I had tabs or I had to fly out, it'd be part of it, but here we
just want to navigate to it. Let's go ahead and do that. What we're going to
do now is we're going to say Routing.RegisterRoute, and this is going to
take in two things. First is the route itself, so I could say DetailPage. I can give it the DetailPage. It could be detail. It could be
whatever I want the string to be. I like to use the name
of property a lot because in C# if we refactor, it will also then cascade down. Then we're going to
associate with a type, so we're going to say
typeofDetailPage. There we go. This is really nice. This gives me a string of
DetailPage to navigate to and a type of DetailPage
to navigate to as well. Perfect. Now let's do
some navigation before we actually pass some data across.
Here's what we're going to do. We're going to come
into our main page, and there are several
ways that we can add navigation when we click on an
item in the CollectionView. Here we can say selected
and we can see that there's a selection change event
and a selection mode. That is one way if we want to register an event with
the CollectionView, which is an option. Now, I'm actually going to say
SelectionMode is none here because we don't want to use
the built-in selection mode. Because we're just doing navigation, we're not actually
selecting anything, I'm more like tapping on an item. What I want to do here
is on the Frame itself, which is housing in this label, is I want to add a
TapGestureRecognizer. This another powerful feature
is that there's tons of built-in gesture recognizers and one specifically that
we'll use is the tap, but there's also a swipe, a pinch, a pan, a drop, a drag, but here we're going
to use a TapGestureRecognizer. Now, inside of here, you
can assign a tap to that, or specifically a command, which is very nice, similar to our SwipeView above. You can also say the
number of taps required. If you have something
you need to tap 10 times, you could do that as well. I'm going to go out
and simplify this here and I'm just going to
go ahead and copy and paste the command from
our swipe to delete, and then we're going to change it. We saw it earlier is that we
needed to get access and say, please do some data binding up
the stack to our MainViewModel, and here what we're going to do is instead of going
to the DeleteCommand, let's go ahead and say the
TapCommand, for example. Here what we're going to do
is pass in a parameter of the string that was
bound to the label here. Now in our MainViewModel, we need to go ahead and
add that to that command. We have the DeleteCommand there, let's go ahead and add
another async Task this time of Tap pass in a
string of s. There we go. Now what we're going to
do is go ahead and make this an ICommand that again is going to do some
source generation for us so it generates the
Tap command for us. Now what we're going to
do is we're going to go ahead and do some navigation. Here I'm going to say await. Again, we're doing this
async task because it's actually doing the navigation, and this is going to use
the shell navigation, so Shell.Current.GoToAsync. Now, what I like
about this is that I can just pass it in
the DetailPage or that route identifier that I
defined in my AppShell right here. I can also pass at
the string directly, which is also very nice. If I wanted to I could come
in back into my MainViewModel here and replace this
hard-coded string with the name of DetailPage. Now, this is going to
tell the shell to go to that DetailPage directly, which is pretty awesome. Let's go ahead and compile
this up and start actually tapping on an item and then doing
navigation to that DetailPage. Again, this is up to you
if you want to reference the DetailPage there or
if you want it to be a string or have some association, totally up to you and your
application architecture. Now let's give this a second to compile up the
application and deploy. >> Our application
is launching here, and let's go ahead and add
an item into our list. Again, apples, when you add, add that and I'm going to do a tap
event and boom, just like that, we've navigated to a new page and
we can see welcome to.Net MAUI. Now, the other thing
I'm able to do is, of course, modify that XAML, so if I want to say font size of 25, for example, I hit "Save" sure enough that's
going to update there. We can also add a little bit of
padding here of let's say 20. Now we get a little
padding there, perfect. Now, that's pretty great that
we just did some navigation, but it sure would be great to pass the actual detail page information, so for example, the item I selected and additionally maybe add a button here that says go back. That'd be pretty nice. Let's
go ahead and do that next. Here is what we're
going to do, is we're going to stop debugging, we're going to go into
our main view model again and now what we're
going to do is we're going to pass it information and there's
two ways of doing that. The first way is to add
it as a query property, and this is very similar to a URL, so for example, I can go ahead and do some string
interpolation here. Here I'll do some detail page and then what I'm going
to do is I'm going to say a question mark and then I'm
going to say text equals. That is going to be
my query identifier, so that's the ID there. Then I can pass in s for example, which is the string that was tapped here to go ahead and
pass that along. This is really important
because this enables me to send simple data types like
strings and integers across. But what if you had
a complex data type, like a person or a monkey or a
car or some other data object? What's great is that
you can pass not only through the
query property here, but you can also pass in a new
dictionary of string object, which is your key values. For example, here, just
go ahead and fills it in, I could for example say, what's the detail page
and ask for example, or I could pass in a new
object of something, whatever it is inside of here, and you can pass that
information across. If you have complex data types, it works exactly the same as
simple data types but you have this big bucket dictionary
here, which is really cool. I'll link to documentation in the show notes and exactly
how to do that as well. But I'll just go ahead and
pass a simple data property across of the string. How are we going to get that
string into our detail view model? Well, we can add a query
property in one of two places. We can do it in our detail page, which would be okay
if we didn't have any MVVM and any view models, but we can also add a directly
into our view model itself. On the top of this, we're
going to add a query property. This is really cool and the
query property takes in a name, which is going to be the name
of the property inside of the detail view model to
bind to so we'll say text, that's what we're
going to name it and the query property
ID of text as well. Again, this property
here that's passed in is going to be the same exact
one that we registered here. If this was ID, for example, then you change this
to ID, just like that. I like to name them the
same. That is just me. It makes it simpler
for me to remember. But now we need to create
this text property and we're going to create one that we're
going to do some data binding to. I'm just going to say string
text and I'm going to mark that as an observable property. Again, the reason that
this data binding to text will work is
because if we go into our dependencies and look at our analyzers for our community
toolkit that we brought in that went ahead and it generated those properties
for us automatically, so there's the text
and it does all that changing for us,
which is really nice. Keeps our code really simple
and that's why I absolutely love the.Net Community
Toolkit for MVVM. Now let's add one more thing which, maybe a way to navigate back. I'm going to do another async
task here and say, go back. There we go. Now
what I'm going to do is await on Shell.Current.GoToAsync. Now to go backwards, I don't need to reference
the main page because I would actually push a
page on to the stack. I want to navigate back
and some of the way how you would navigate
around the file system, I'm going to use dot dot, and that is how I'm going
to navigate backwards. You can also do
additional navigation at any time by adding
a forward slash, so that would navigate back
and then to another page, so if I had detail or
I had a monkey page, for example, that would
navigate to that page, and you could do that
a bunch, for example, go up two pages and then also
pass parameters back and forth. It's really nice. Now
we're going to do is also mark this as
an ICommand because that is going to go
ahead and turn it into a command for me and it'll
be called Go Back command, that will be automatically
source generated. Now what I'm going to do is go one
more time into my detail page, and instead of doing
Welcome to MAUI, we're going to do some data binding. We also need to do our
association to our data type, so that way it's compiled and bound. I'm going to say a new xmlns
namespace, a view model. In here, I'm going to type in
view model and it's going to find that it's in this namespace, so we're creating a XAML
namespace and I'm going to say x data type and that will be a view model to the
detail view model. Now what I'm able to do
is do a binding here to the text property. There it is. Now, let's also create a
button here and say text, go back and then what I'm
going to do is register the command to the binding of
Go Back command just like that. Perfect. Now, let's go ahead
and do some data binding again. All set up and see our navigation. What we want to see is
whatever item I tap on, it should go ahead and
navigate to that page and then automatically set the text
property when I navigate. Now we have our application
up and running. I'm going to say apples added there. I'm going to add oranges as well. When I tap on one, sure enough, we have apples and a Go Back
command that navigates backwards. Oranges go back apples go back. We just implemented
navigation to and from pages, back navigation and the ability
to pass query parameters or full objects using the built
in navigation system of.Net MAUI. There you have it, you've just done some navigation and in
your.Net MAUI application. We've passed data from
page A to page B, and we figured out how to
navigate back as well. Now, what we're going to do next in the.Net MAUI Beginner Series is take a look at how we can
integrate native platform APIs. Now.NET MAUI gives you them
inside of C-Sharp but also gives you an abstraction of our common platform
features such as sensors, geo location and connectivity. Stay tuned to the next video in the.Net MAUI Beginner
Series to learn more.