If you've been working with Shell in
.NET MAUI, then you probably know that it can be a bit of a pain to manage all
the routes and stuff, but not anymore. With this plugin that
uses source generators. Let's go check that out. For those of you who don't know what
Shell is, you've probably already used it without you even knowing because it's
part of the default templates in .NET MAUI. It is a concept that was
already built during the Xamarin.Forms era, but now it's in .NET MAUI
and it's kind of like your opinionated implementation on how
navigation should work, how things show up in your menu
structure inside of your application, top tabs, bottom tabs inside of your
flyout menu, that kind of stuff. So it is really easy and really
powerful stuff to get your app started with that. But if you've
looked into it and used all the power that Shell has to offer, namely the URL
type navigation that is built in, which is really cool,
then you probably already know that the URLs are kind of like magic strings, right?
And that's typically something that we want to avoid. So we can get around
that by using the name of of the pages and register routes that
way. But still, it feels kind of like not great. But now there
is a plugin to make things a little bit better, at least in terms
of managing your things. It uses source generators to generate the
routes in a static class that you can use inside of your
application to go to a certain page and whatnot. Let's just dive into the demo
and show you what this is all about. So here we are in Visual Studio 2022.
I'm going to show you this today on Windows and also running the
Windows .NET MAUI client. But this lives in the .NET MAUI layer,
the abstraction layer. So this works out of the box for all the platforms
that are supported, iOS, Android, Windows, macOS. You don't need to do anything
special. It will work on those platforms without needing to change a thing. So
here, this is just a new .NET MAUI project. I can run this
and you will see the new template that we introduced
for net eight with the cool race car with the 8 on it, little Easter
egg there, and the button that will increment whenever we click on it,
right? So we've got all that now let me add a very simple page and show you
the very basic mechanics of shell. Like I said, without you even
knowing, you're probably already using it because you can see AppShell right in
here, right? So that's there in the template. If I add a new page,
right click on my project, add new item, I go to
the. .NET MAUI pane here on the left and we
see all the things specific to .NET MAUI. Let's do
a content page and let's call this SomePage.xaml. Doesn't really matter. So
we get a new page with XAML you can do it in code if that's what
you want. Welcome to SomePage, right? Now we have this one and we can actually get here by now doing
URL navigation. So go to some page. So to do that we can go
back to our main page, go back to our code behind. So
let's go to my Solution Explorer, MainPage code behind and instead of this
button to increment it let's do some navigation here. So
let's remove this code that's code and what I can do here now is say
Shell.Current. So we have a current object that
represents our shell of the application. Of course if you want to
be a good citizen and use MVVM and view models then you probably
want to make this into a service and inject that inside of
your view model, right? So current GoToAsync and we got a couple of overloads here. But
the most easy one is just specifying a string here that
goes to some page. You can also do like the URL with
slash and dot dot slash and that kind of stuff. But you
can also do in the simplest form same page, some page, excuse me. And
now it will go to some page. Well actually I need to
register the route first so this won't work just yet. So go to my
Solution Explorer again, you can register the routes anywhere
but kind of like your typical place to do it would be in the AppShell. So here
we can have the AppShell and we can say routes... Actually it is Routing.RegisterRoute and we can say SomePage and we can say typeof(SomePage). So now it knows like hey we have this SomePage
route and then whenever we see that route,
whenever someone navigates to it, we need to get that some page out of our code
base and that will be used to navigate to
and then this of course this key has to correspond with whatever we
navigate to here, right? So it doesn't really need to
correspond to whatever that page is called but typically that is how you would do
it. So if I run this now and we click the button then now it
will go to this SomePage, right. We will see this new page
coming up and it will go to the SomePage and I think there will
automatically be a button to go back as well because this just uses a
navigation page under the hood basically. So if I do this,
you can see welcome to some page. And here I have this button to go
back. So now I can go back and forth. So now we have this URL
type navigation. But you probably already also mentioned, hmm
Gerald, this isn't really great. Like if I'm going to change
something here with changing this register route to some page one,
now it's not picked up here with this SomePage, GoToAsync.
And now suddenly things are broken because if it can't
find it then it's not going to do anything, right. It's maybe going to
give something in my output like hey, I cannot find this route but otherwise
nothing will happen. So that's not great. Now what you
could do obviously to make this already a little bit better
is if you want to keep the same name for your page and
the routes anyway, then you can say, hey, I want
to use name of some page. And now we're good, right?
Whenever something changes, this will automatically be picked up
and everything will fall back in line or at least it will break at
compile time and not runtime. So now everything will be all right
again. We can do the same thing here, name of some page and boom,
we're done. Right now it works again. But if you
are going to use this in a more MVVM context, and you're really
strict about not breaking the MVVM pattern, if you're
now going to reference pages inside of your view models, that's a big no no,
right? That's not something that you want to do. Look, it works again. So what
you could do is kind of like place all your
routes inside of a static class and reference things from there. Use
magic strings or the names of whatever you want to do there. But still, that not
feels great because you have to maintain that yourself. And
that's kind of like where source generators come in. So my good friend Julian has
created this cool package that will generate this for you
automatically. So let's see how that works. I actually already installed it
on my project right here. But let me just show you real quickly, right? Click on
your project Manage NuGet Packages and you want to search for epj.RouteGenerator. Actually I have it here in my history
probably. Oh, there it already was. See he has a
couple of other plugins so definitely go check that out as well. But here he
has the RouteGenerator. Make sure that you have the
include pre release checkbox on for the time being at least,
because it's only in pre-release right now. And this automatically generates
root names for navigation based on a class name convention for .NET MAUI
applications. So I already installed it else install
it and it will do that for you automatically. All the things that
are needed. Then what you want to do is go over to your
MauiProgram and we need to add a little attribute here. So
what you need to do here is do [AutoRoutes]. You can already see
it and then we can specify a suffix. So now we do Page and with this we kind of
configure that everything, all the pages that end with page inside of our
project will get a root generated. So I think
whenever I start building this, actually maybe it
does it without building. If I go to dependencies here and then windows and
analyzers, you can already see a note with the
name of this plugin. That's how source generators work. You can see
the code that is generated in here and we can inspect what is going on. So we
have this one analyzer here and you can see it does Routes.g.cs. The g is
for generated. So we have this and you can already
see it picked up on main page and some page. So it created that
for me. This const string main page. It does work with magic
strings but that now matters less because when something gets renamed,
this entry goes away for the main page and we have breaking changes because
we are referencing that main page, right. So that's something that will
be picked up automatically now still and this is done automatically so we don't
need to maintain that ourselves. We also get a public property for all
routes. So you can get a list of all the
routes that are in here. It's probably something that will come
in useful at some point. So what we can do now we have this auto routes page
and what we can do now we still have to register it. I think
there will be a nice opportunity here for also to the source generator to
register routes from that same plugin. That will be
super cool that you don't need to maintain this yourself as well. And what we can
do now is here say routes some page you can see that we have
intellisense everything main page some page all the things are here and
you can just reference that from this thing right here. So we can do that
and the same thing on like the navigation side. So here we can do
routes SomePage, right. And if I go back in
now, it won't be a surprise that it still works, right? Because
this ties everything together and we can navigate from one to the
other. Whenever something changes, whenever I'm going to rename the SomePage now, this will suddenly generate
something else. Our source generator will do some page something and it
will break our build at compile time. And you know, something's up. I
need to fix something. So that is really powerful stuff. Now, one
more thing, what you want to do, like now you
probably have some page at some point. That's always how it happens. That is
the exception to the suffix thing. So you don't want to name something
page because you want to do this dashboard. We're going to add a new item which is
going to be called dashboard. So let's do Dashboard.xaml, right? So we get that in there and now
nothing gets generated because it doesn't have that page suffix. So
let's change this text right here to something important. Did you
subscribe? Subscribe to my channel yet? Maybe that's something YouTube channel
like and subscribe down below. So there's this new cool YouTube
feature where I say subscribe down below that, the subscribe button
lights up. Does it do that for you? Let me know down in the comments. That
will be super cool. So did you subscribe to my channel yet? Maybe
that's something that you want to do. But now we have this dashboard and what you
can do is go back to the MauiProgram and we have this extra
attribute with the extra, was it extra, ExtraRoute? See, there
it is. And now we can just register something that we want to do in here.
So we have this dashboard right here. Of course, this kind of like breaks
whatever we are trying to do here, because now we are specifying this dashboard thing as a thing and we
are kind of like moving this magic string from here to another
place, but it's still nicer than having to
maintain that yourself. And it's probably not going to be
renamed at some point anyway. So now what we can do is also have
this route. So we have this dashboard right here. So that's there,
and we want to, of course, do this dashboard. And we can now
navigate to the dashboard from here as well,
just to show you that it works and to give you one more reminder that you
want to probably subscribe to my channel. So this is how you can
use this cool plugin to make the routes management
basically of your .NET MAUI Shell application so
much easier. This seems pretty useful, right? No
more manual management of all the shell routes right there. It feels a
little bit cleaner, although it's kind of like still the same thing, but
managed for you at least, and it will be generated automatically. And
everything that's generated by a computer will be much less prone to errors than
when you're doing something yourself, right? So that's a big win.
And the less I have to type myself, the happier a developer I am. Julian,
thank you so much for creating another wonderful package to
enrich our .NET MAUI ecosystem. The community loves you, or at least I
do. And Julian also writes a lot of wonderful blog
posts, including one about this great package. You can find it down in the
comments below, so make sure to check that out. And I have some thoughts
about this packages. Like it would be super cool to also have the route
registration through this package, right? So that you don't have to worry
about that as well. And that goes automatically. So we'll see what the
future of this package brings. Let me know your thoughts down in the
comments below. And I'll be seeing you for my next video, which might be this
one. See you for the next one.