Learn .NET MAUI - Full Course for Beginners | Build cross-platform apps in C#

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
have you been looking to kick-start your journey with native cross-platform desktop and mobile development with donna maui well you're in the right place i'm james montemagno and i'm a long-time dot-net developer and specifically a long-time cross-platform developer with xamarin xamarin.forms and now don maui i work at microsoft and our developer community team inside of the developer division where the team members build donna maui visual studio and many many other developer products that you use every single day before that i worked at xamarin as a developer advocate helping developers around the globe learn xamarin technology and be successful building apps and before that i worked at a company that all i did was build production applications for them for tv software and hardware which was really exciting i fell in love with xamarin which is why i've been doing it for over a decade and while i'm now here all about donna maui the next evolution in building native cross-platform desktop and mobile applications all with c-sharp and net so you're in the right place if you want to get started because i have built a all-day workshop that you can follow along at home it's going to take us from start to finish and you're going to be able to build and understand everything in a don maui application from just getting started in displaying data to making web requests and pulling that data from the internet and displaying it in all sorts of lists to doing navigation and going and passing different data around from page to page and we're also going to take a look at the many ways of styling applications and adhering to light theme and dark theme so your customers of your applications have the choice and by the end of this you're going to have a great app that you can put on your device or on your emulator or simulator you can show it off to all your friends and if you want to go even further of course subscribe at any time during this video because i put out videos nearly every single week right here on my youtube channel you have years of different back catalog live streams and produced videos for not only don and maui but xamarin forms before that in which many of them are applicable to don and maui and of course c-sharp and net tips and tricks along with all sorts of things such as emulators and simulators and just what's new and going on so make sure at any time you like this video that also helps the channel and of course it recommends this video to other people now what i'm also going to be doing is putting time codes all along these chapters are going to help you skip to and from so if you're not around for the next few hours and you want to come back later no problem pause it close it come back later bookmark it you can find those below or in youtube just use the chapters feature that is built in now this is a multi-part workshop specifically six different parts and each of them are some longer and some shorter each of them are broken into two different parts you actually have first me giving a presentation on the different pieces that we're going to go through and then we have a live coding workshop part in which you will actually be able to get visual studio start coding along with me with a full readme now the advantage of actually following along with the video is that i'm going to explain in detail every single thing that i'm doing but at any time you can pause take the code snippets browse the detailed readme that i have and of course get the code into your application now since i can't update youtube videos later on some things may be a little bit different but i'm going to try to keep things as consistent as humanly possible as done maui evolves over the years so you can come back to this workshop at any time and of course if anything changes drastically i'll re-record the whole thing so make sure you subscribe like this video and ring that notification bell so you get up to date right here on youtube whenever i put on new videos this is going to be a long journey and i hope that you're excited for it so what we're going to do is go ahead and get started [Music] all right let's get started learning how to build native cross-platform desktop and mobile applications with dana maui now if you're interested in what done maui is how it works and how you can extend it with blazer well you're going to watch a video up over here because i already did that video in deep deep detail and that's usually how i open up the workshop so people have time to install visual studio or visual studio for mac and all the dependencies to get started with don and maui and get things set up on your machine now i recommend you definitely check out that video in deep detail i went through a whole presentation going through every little bit humanly possible of exactly how done maui works and everything that's built in to done maui itself now i'm also not going to go in this workshop in detail on the installation because installation can change over time on both mac and on windows and new visual studio versions are always coming out now i do have a video that is on the channel that will walk through many of those aspects but for this workshop i'm going to recommend that you go to the documentation which is linked in the github repo at aka.ms forward slash maui workshop now that's really important because that is going to have the most latest and up-to-date information on exactly what you need to do to install don maui now i'm going to be doing a lot of work inside of visual studio on windows but we will hop over to visual studio for mac so we can see the application running on both ios and mac now i like doing a lot of my development on windows because i've been a long time windows developer and i like it a lot because i have android available to me right away and if you're on windows 11 you can use the windows subsystem for android and of course you can do windows development which is super crazy fast now you also have the option of plugging in an ios device directly into your windows machine if you have an apple developer account and deploying your.net maui application directly to your iphone without any mac at all you also can connect to your mac as well and of course all of this is inside the documentation so i highly recommend you check that out all right let's talk about what is in the workshop and let's get started so the first thing that we're going to do today is we're going to learn how to build our very first application and what is inside of the project structure of don maui we're going to take a look at mvvm and data binding and many of the libraries out there that'll help us be even more productive when doing mvvm and xaml development we're going to do navigation so we can push and pop pages and display different pieces of data and learn how to pass full objects around our application all using a uri-based schema we'll also take a look at accessing platform functionality so if you want to access geolocation preferences or sensor data we'll be able to do that we're also going to look at displaying data in a lot of different ways how to do things in grids and columns and rows horizontal vertical there's a whole bunch of different ways of displaying data that you can optimize in your app so you can handle scenarios like there's no data in my list what do i do and then finally we're going to take a look at app themes now app themes are the things that are going to enable us to do things such as do light theme and dark modes in our application and of course re-share themes and styles throughout our entire application so we don't repeat code over and over again now this is the six fundamental pieces of the workshop at the time in which i'm recording there may be new modules added later on many people have asked me for new modules and hey right now is a great time to say what else would you like to see go down into the comments below and let me know what you want or if this looks great give it a thumbs up on the video and we'll continue on now a reminder over here that all the code is available at aka.ms forward slash maui workshop this will take you to the dotnet presentations organization on github which has not only the donna maui repo for the workshop but also asp.net core blazer c-sharp and so many more workshops and presentations that you can get your hand on if you want to learn different pieces of dot net technology all right let's get into it building our very first application the first question we need to ask ourselves is what is inside of a.net maui application well the project that we are going to be working with is the monkey finder solution here and it's going to enable us to find monkeys all over the world put them on a map and use geolocation to find the closest monkey to us and we'll also be able to tap on a monkey to go deeper and find information on a detailed page now this is what the project structure of a donnie maui application looks like it is one project inside of one solution now when you do file new it's not going to have as many files as this but it's going to have quite a few of them to be honest with you i've gone ahead and added some of the default dependencies that i'll walk through when we're going through the code and i've also gone ahead and scaffold it out or created a bunch of the pages and boilerplate blank code so you have to go ahead and add a bunch of empty files at any time everything that you need is in there but everything inside of a don and maui application is a single project and that's one of my favorite parts of donna maui every single thing is inside of here including all the source code the user interface code shared resources platform code and so much more we're going to take a look at fonts and resources and images that are all shared cross-platform which is awesome and like i say here what we can see is that we're not we're also going to have a resources folder and inside this resources folder is going to be all of the fonts images and raw assets across all of our projects what's great here is that don maui takes care of all of the different parts of the application including handling setting cross-platform fonts taking svgs or pngs and rescaling them for the specific project that it's on and it will even handle app icons and splash screens as well which is really really cool and you can find all of that inside of the resources folder and you can add your own so if you want to add your string translations in there you can put them right there too and everything will be shared across all the apps now another thing that it has is a platforms folder now by default this is going to handle all of the project setup per platform for android ios mac and windows every single platform has a little bit of boilerplate code that needs to bootstrap the application but you can also come in and write platform specific code for android ios mac or windows right inside of these folders you don't have to do any conditional compilation if you don't want to because inside of the android folder it knows that only android code can live there now you can write platform code outside of these platform folders which i'll show you in a little bit but you do have to do some conditional compilation now i love this because it just puts everything in one spot that i can just see it just makes it so enough to set a bunch of different projects in the startup it's really really nice now this project is actually multi-targeted and what that means is that this project targets multiple frameworks what we can see here in the target frameworks is that by default every single done maui project will target android ios mac catalyst and windows as well you can remove these if you don't want to ever have them in your project and you can delete those folders but you might as well keep them there they're not hurting anybody now what's also great is that tizen is also supported which is a platform from samsung for different phones smart watches and televisions and that is also in the default project if you want to install the tizen tooling but those platforms are supported from samsung not from microsoft like android ios mac and windows r now there are a bunch of other little things inside the project folder that are so great for doing cross-platform development because everyone is going to need to set a title an app id and application versions and you can do them all here these are just some of the settings that are available inside of the cs prod or the csharp project file that will automatically be set whenever you compile that ios android mac or windows application there's a bunch more and we'll take a look at that when we go through the code now i did mention that you can write code inside those platform folders but you can also do conditional compilation this enables you to use these pound if definitions to say if i'm on android let me access android specific code or have code run only on android here you can do elsifs for ios windows there's a bunch of these identifiers that help you access those things now this is only if you need to access platform specific features inside of don and maui if you just need to write code for ios or android there's an api in down at maui that will detect what platform it's on so for example if you want an integer of count to start at zero on android but 10 on ios you can say if the platform you're running on is android start at zero else on ios set it to 10. that is available in code as well and we'll take a look at that as we run through the workshop live together now one of the most important parts of the dotnet maui application is the startup project this is where you're going to scaffold out everything that is needed to start the application from start to finish and this is about what the default project template looks like it creates a maui builder it sets the application class as the maui app to start it configures the fonts that are in the default templates and then it builds that up and returns the maui app so it can start it up now this is also where you can register dependencies with a built-in dependency service and i have a full video on that but we'll also be touching that inside of this workshop there's a whole bunch of other different events such as life cycle events and a whole lot more that you can access right here so definitely feel free to read the documentation to learn so much more but we will definitely be inside of this project startup class right here doing a whole bunch of configuration for our monkey finder app like i said you can add different dependencies inside of the startup project like we're going to be doing in this application and you can even register your pages what's great about this is that in the application that we're building we're actually going to be using dependency injection and inversion of control and constructor injection to automatically create and inflate all of our dependencies this is really great if you're coming from asp.net core or other frameworks that have this similar builder structure you're going to feel right at home and if you're new don't worry because i'm going to tell you how all of this works as we build the application live now i also want to mention that there's a bunch of different lifecycle events that are available too there's traditional lifecycle events in the application class such as start sleep and resume but there are a whole bunch of new windows events too and by windows i don't mean windows operating systems i mean the windows on the screen that's right dot-net maui is a multi-window enabled application now many of us may not use this but if you are on desktop or on tablet this is really nice you can create new windows and each of those windows have their own state so by default when a window is created you can link into all of these different lifecycle events if you need to do specific things when the window is stopped or resumed or deactivated and you can see on the bottom left here all of the different ways that the window can start and stop it gives you much more granularity when you are creating and managing your application so if you do need multiple windows you can create new ones but by default there is one window and one application in every single dotnet maui application but just note that there's a whole lot of deep dive that you can do and of course everything is documented and of course i'll put links to the documentation below now i did mention that it is multi-window so here's a great example of the weather application from david orr now love david on the down at maui team showing you that you can just new up a brand new window set the page and then it'll just open a new window automatically and that's what his weather 21 application is doing now one of the other important pieces of donna maui is the shell this is the base of your application i have a whole video again all on shell and why i love it and it is part of the default template when you do file new of a dot my application now this is what enables uri based navigation but it also gives you an opinionated way of structuring your application with outs or tabs that can go on top or on the bottom so here for example we have a shell with different fly out items that are going to be used in our flyout from left to right you can also add tabs you can add tabs on top and on bottom it really helps structure your application in a great way now i like to use shell for all of my applications and like i said it is the default template so i highly recommend it because there's so many great features that you're going to see today as you do the workshop now let's talk about how pages are formed inside of a donet maui application and inside of a shell a page is the root it is the starting point of anything that you see on the screen every single shell has pages and those pages are specifically a content page and it holds specifically one visual element for example that could be a control maybe you want to have one button and every page can have one big button in it that's important to know that inside of a content page the main content is one item you can't have multiple items inside there unless you are using a layout now there are many different layouts that i walk through inside my what is don maui video but there are things such as stack layouts relative layouts absolute layouts and so much more so instead of just having one control in your application you're probably going to have a layout first such as a grid and what's great about layouts is that they can have a bunch of controls inside of them so for example you might have a stack layout with labels and buttons and images inside them all stacked up with different spacing you can have layouts inside of layouts so you can have a scroll view that has a stack layout that has other stack layouts and different elements inside of it too so it's very flexible so you can have all sorts of things no matter what your application needs and like i mentioned there's a whole bunch of different layouts one of my favorites that's a little bit complex but oh so powerful is the flex layout you'll often see us use grid or stack layout because those are the easiest to layout different pieces of content and often for me at least i can easily wrap my head around a grid because there's columns and rows we've all used excel or a stack layout where we stack things up over and over again horizontally or vertically but again there's a bunch of them and there's a bunch of new ones in don maui too such as the vertical stack layout and the horizontal stack layout that are optimized for laying things out horizontally or vertically now built in to every single element or control or layout are a bunch of different behaviors or events if you will every single control has a bunch of different properties they can be created completely in xaml or an xml based markup language or inside of c sharp themselves and there's a great library in the donet community tool kit that enables different c sharp markup extensions to make that c sharp code a little bit less but here for example i could create a new entry with a placeholder of enter text and set the keyboard here i can then register and subscribe to different events such as text changed and then do different things when that is happening i can of course create that directly inside of the c sharp or i can add that event inside of xaml as well so like i said the controls expose properties and they also expose events too now that's not to say that we don't have mvvm and data binding because we do we're going to take a look at that in the future so let's go ahead and do it let's actually create our very first page of our application that displays a list of monkeys that we're just going to hard code into our application and this is where we're going to start so you're going to make sure that you open up that repo over on github at aka.ms forward slash maui workshop and we're going to get started so let's head over there now all right let's get into it we're going to start by building our very first application and again what we're going to do is do a quick walkthrough of everything that's inside of the github repo for the workshop today that we'll be working through additionally what i want to do is show you some of the differences of the project that we have inside of there and the file new project that of course is always tweaking so there might be some differences as we go through so let's head over to github right now all right so when you go to ak dot ms forward slash maui dash workshop it's going to bring you right here to the net presentations repo now if you don't know what this repo is as organization it's part of the.net foundation and you can find a whole bunch of different workshops so asp.netcore.net core maui stuff whole bunch of stuff in here blazer workshop c-sharp stuff there's a whole bunch of stuff all the 20th anniversary for net is all right here which is really cool so definitely check that out now inside of this repo how i sort of organized it let's bump up the fonts a little bit more is each one of these parts so part zero part one part two you get the idea there's a big readme here so you know it's super important to go through look at the setup guide you know take a look at this quick tutorial that i highly recommend emulator hardware setup that you may need and then of course i walk through all the different parts so we kind of already walked through part zero but one thing that i do want to talk about here is that in part zero i really go through a deep dive of every single thing that's inside the different projects so i'm going to go ahead and do some of that stuff today but the biggest thing that we want to do is start in this part 1 display data every single one of these parts has a beginning project and a readme inside of it so part one here has a full readme this is what we're going to walk through in general i'm not going to walk through it i am going to walk through it but i'm not going to read it and copy code i'm going to do it live but you can follow along at home and then there's a project now you can take this solution this project that we have right here today and take it from start to finish now one thing that i did though is i wanted to make sure that at any time if you had to leave or you got stuck you could pick up or imagine if you're doing this in person you came in and you walked in on part three well there's a starting project solution there and of course a readme which is super duper nice so that's sort of the guide part here so what we want to do is first clone this so i like to hit this code button hit clone and we're off to the races i'm going to go ahead and open up visual studio 2022 here on the pc and what i like to do is come in and do the clone repository setting here so here's this boom and just paste this in here now by default it may put it into like a smaller folder what i'm going to do is i'm going to put it onto my d drive slash i think i have github demos just a shorter url in general for me to to get going there but of course you can always hit a file picker and put it there just there are a lot of parts inside of this thing so make sure you put it in a relatively decent folder there all right now what i'm going to do is i'm going to go ahead and open this over on another screen so i can kind of at least walk through myself what you're going to be doing but let's go ahead and take a look at the solution explorer inside of visual studio we can see that we have all these different solutions we actually have a finished solution part 1 all the way to part 6. so inside of you know the first part what we're going to do is open up this part 1 display data monkey finder sln all right so this is going to open and i want to walk through some of the things that i've done here in this solution so i'll kind of zoom around a little bit but in general this is going to be very similar to a file new project but i have already configured a bunch of default nuget dependencies that we're going to learn about i also added all the pages and the view models but i didn't necessarily actually add any code so if we zoom in here we can see a few things the first thing is that we have a readme so here's the readme reme.md so if we open that up we could actually see the readme right here which is nice we also have these directory build props so these are common properties across all of the projects in the repo and also this build target so this thing here is going to give me access to some common nuget packages for all of the projects and the reason i did this for the workshop is because i didn't want to have to update a bunch of different projects every single time i can use these nice build directory targets here but for the most part you don't need to worry about those now inside of the monkey finder we're going to find all of our dependencies so we have our android we have our ios we have our mac we have our windows built on wind ui 3 and the windows app sdk now if i go ahead and look at the packages here we can see that these are the different dependencies that i have going on which is pretty cool now this is using the default file new which uses a shell and an app file and a maui program but let's first walk through a few common things that we have here the first thing is the platforms folder this is what i talked about earlier we have all of our resources things for android specifically there ios our info p list which would put any specific permissions that we may need we'll talk about that in a future part of this workshop same with mac catalyst and also windows as well in our resources here we have our fonts images and our raw assets which are really nice we have fonts images and we have some raw data here we're going to talk about that here in a little bit too and then of course we have our different app icons and our splash screen configuration there now the other folders which are model services view and view models those are the ones that i've added uh and i and you can see i have a few pages here a few view models that we're going to talk about and a monkey service because we're building this monkey finder application and we have a monkey as well the reason i did this is just to save time you can of course right click say add new item and here you're going to find all of your item templates for your classes and for net maui so if you want to add more pages or resource dictionaries or content views you can add them there too now if we double click on the monkey finder over here what we're going to find is our project settings so we're targeting ios android mac and of course windows when we're on windows here we have our single project and we're using implicit usings we also have an application title which is monkey finder we have an application id and a grid for windows and then we have our display version and version code now the use interpreter this is only on a debug and i believe that the team actually enables us by default anyway so we may not even need that as things sort of evolve we'll also see down here is that we have our app icons our splash screen configuration our images and our fonts and our maui assets here which is quite nice so these are all things that are cross platform brought in by net maui for our application which is really really neat now one other thing that i added here was this global usings and this is just nice because i didn't want to have to worry about us adding a bunch of namespaces when we're looking at code so these are just global usings for our projects for system diagnostics text.json and things like that so what do we have first and foremost well what we're going to do is we're going to build a monkey so we're going to need to have a monkey itself here it is very cool now this monkey data is going to be coming specifically from a json feed and i'm going to bring it over and if you are in the readme you'll find it here here it is it is a bunch of data of monkey so they have a name a location details image which is a url which is nicely hosted on github which is awesome and we have a bunch of them in here which is nice now we're going to go to a website called json2csharp.com and this is a nice website because it enables us to convert json to c-sharp as it says there so i'm just going to copy this and we're going to go ahead and paste that in which is nice and then i can hit convert and just like that it gives me everything that i need so we have our our json here and i can copy it to my clipboard which is quite nice all right so if we go ahead and paste this in here we're going to see that it gives us this class root it doesn't know what it is necessarily so we can go ahead and delete that and we specifically are going to be inside of this monkey there we go so that's a nice way to do that there another cool thing that's inside of visual studio 2022 is if you actually come in and copy that you can actually do edit and then there's a setting called special paste over here let me go ahead and bring visual studio over so you can see it edit special paste let me bring it over a little bit more here because it's a windows cut off there we go edit special paste json as classes and sure enough if we take a look at that we can see that well it put it right in the middle but it it went ahead and it gave us all the different information i'll do that one more time here just so we can actually see it edit special pace json as classes and it gives us our information which is quite nice now it's a little bit hard to say this one did do floats instead of doubles so you always kind of want to double check exactly what those magic converters are doing but our monkey has a name a location details image population latitude and longitude now at this point we are not going to make any additional code changes at all so what we're able to do is come in and start up our application so here i could set the android system here as the startup and then you can pick an emulator so i have two emulators here so it's up to you what you want to use so you can pick and choose what you have you can also come up to tools android and there's an android device manager here you can pick that up there and what this does is it enables you to create and delete different android emulators now if you are on windows 11 i would definitely look into the windows subsystem for android it enables you to run your android applications directly on windows which is really really cool so definitely take a look at that which i love else if you're on windows 10 or on windows 11 where wsa the windows subsystem for android may not be available what i would recommend doing is taking a look at the documentation i linked to to make sure that your emulators are all super optimized which you know would be great now i am actually going to start not this one i'm going to start the one with google apis specifically and the reason i'm going to do that is because we are going to use a map application at some point here and that map application is going to need to have a map as well so i'm just going to set up my emulator here cause i'm always messing around with it and i have an android emulator now i have my emulator set to set on top so if i actually go into the settings and i go into settings here we can see that i have my use detected adb and emulator always on top it's one of my favorite settings which is quite cool so we can go ahead and set that there now i could have also just launched it by hitting debug as well totally totally fine to do but what this is going to do is sort of now compile up my application it's also going to verify that my android emulator is started and if it isn't started it's going to launch it so that's a quite nice feature of visual studio and of course if you're using the windows subsystem for android that will just pop up inside of visual studio now i want to talk a little bit about the build process here as we kind of wait for this to go through and how donna maui and the android and ios build systems work is that they're iterative so the first time it's actually doing a full compilation of all the code all the dependencies and it's having to bundle up a full android package for deployment and debugging and i also want to say that that first build is going to take longer than all other incremental builds and deploys so if you're adding new assets or classes like that may take a little bit longer but if you're just modifying code it's able to sort of do a diff and deploy which makes it much much faster which is one of my favorite features i often find the first build here taking about 30 to 60 seconds for android and for windows it's going to be a lot faster because it's deploying locally that doesn't have to deploy a crazy package and of course ios is a simulator so also quite fast and mac even faster because it's on the machine which is nice so this here we can zoom in and see we're starting debugging it's found our stuff and we get our net splash screen and we should get a blank screen so let's walk through how we got to this blank screen well the first thing that i want to talk about here is that we have some views that we're going to do some modifications on and we're going to spend a lot of time in the main view that's going to be where we display our list of monkeys now every startup of the application starts with an app and our application here has a resource dictionary that we're going to get and talk about in a future video or part of this video in the future i should say but there's a bunch of default stylings that i've added here which are quite nice in the code behind we have this little constructor and this initialized component is going to make sure that that xaml of those resources are compiled and then we have our app shell as the main page and the shell itself which i have a whole video on is a container if you will for our app that allows us to structure the application in different ways such as flyout navigation or top and bottom and if we open that up we're going to see here that we also have some styles for our shell but we're going to have one piece of shell content here and specifically what we see is that this shell content we have different properties like is the navigation bar visible for example and i said that the true which is the default but i wanted to show that off and also the title is monkeys the route here which we'll talk about in navigation or you can think of it as a uri a route is main page and then the content template is this main page now the reason that that is important is because this is sort of lazily loading this page so it launches the app launches this up and then it creates this data template and lazily loads this view when that page needs to be shown which is cool now i can add additional pieces of shell content i can add things into like a tab and tab bar for example and there is a fly out item and a menu fly out and a subsystem so there's all sorts of great things here that you can add but by default you get whatever your main page is which is this blank page there's nothing in it okay there's nothing here so let's put something in it uh which would be uh quite nice so we're just going to start to spec out some things so what we're going to do is add some items inside of here so what what i could do for example is i could put like a button and i could say text equals click me and uh here if i just hit save that is going to put a huge button on the screen that says click any so that's quite nice i'm using xaml hot reload there's also c sharp hot reload and this all happens when i hit save there i can also you know do another one big click me click me click me right and i can say font uh font size equals 100 and make it ginormous right that's probably too big so let's make it 50. uh there we go now a content page can have one item so if i was to try to put another button here visual studio is going to be upset with me so what we would need to do is wrap this thing in a let's say vertical stack layout for example and what that would give me is two buttons right here and we could of course add some spacing let's say 20 there we go and we could add some padding of 20 as well and now we have our buttons that are inside of this vertical stack layout there's also a horizontal stack layout which does things horizontally as you can see but now it's off the screen so that's that's not good at all we don't want we don't want that so we have our vertical stack layout now there's all sorts of different controls that we can put into our dot maui application images buttons labels list views collection views carousel views canva there's all sorts of things there's third-party components there's all sorts of great stuff so here's what we're going to start with we're actually going to delete this vertical stack layout and we want to display that list of monkeys if you remember and we're going to do that in a collection view now there is a list view and a collection of you have a whole video on my channel about the differences collection view sort of the evolution if you will of of the list view and it has a lot of nice options there so it's blank again oh my goodness it's blank and we have nothing in it so what we want to do is we want to fill it with some monkeys which would be quite nice so we can do that so what we're going to do is bring in and reference this monkey model that we created and all these are public so we can access them here so what we can do in our main page is say collection view dot and i'm gonna make this also a little bit bigger just so we have it really big there we go perfect collection view dot and i'm gonna say item source all right now an item source is a list or an observable collection or an array of items and this is one of my favorite features that we can actually fill this collection view with an array so we have all these name spaces up here and we can add our own custom namespace so by default this x is sort of this high level xaml namespace and don maui is there by default which is why i have collection view and you can see this is the default one but i can create my own xm lns xml namespace and here we're going to name that model i'm just going to type in model here and we're going to find our specific namespace that we want to bring in and the intellisense is really nice because it finds the namespace it says all the things for us automatically so here's what we're going to do is normally we wouldn't do this but since we're just building a screen and we're not actually you know we're not actually building a full application that is going to do data binding or anything like that until later in the video in the workshop what we're going to do is we're going to actually create a thing called an array right inside of our list view so our collection view item source so i'm going to create an x array and you can do x string accent 32 all these things i'm going to give it an x type so what type of array is it what is going to be specifically of my monkey model that's pretty cool check that out now what i can do is i can actually create the monkey right here so i can say baboon i can go in and say model name let's do this one of a cappuccin monkey awesome and let's do another model of name and we'll do a red shanked duke one of my favorite monkeys of all time i'm just gonna hit save there and look at this we have kind of if you will uh three monkeys alright so so what has happened here is we have monkeys in our collection view and automatically what is happening is a collection view is calling to string on those items so what that means is that the tostring is just the monkeyfinder.model.monkey if i was to come in and override the tostring method on monkey and just say name location details or something it would output it there but we want to do something different let's say we actually have these these monkeys here let's go ahead and give it a template to use so we can define what each cell looks like inside of our application okay now what we're going to do is we're going to say hey collection view let me set your item template all right and that item template is going to define specifically what each of those monkey items looks like and every item template its base type that we have to give it is something called a data template and a data template enables it to do data binding and lets it take basically look at the data type and be templated and you can have multiple data types so if you had a monkeys and your cats and you had dogs you could actually define multiple data templates too now one thing i'm going to do to help with intellisense and also compiled bindings is give this thing a data type now what this is saying is hey data template i'm going to tell you what type of data is inside of this data template and specifically that will be our monkey right so that's going to be our monkey there that's going to help with intellisense it's also going to enable compile time binding so if we typo something like if we didn't spell name correct and we missed a when we're doing this data template it would automatically give us an error when we try to compile but here's what we're going to do is we're going to do a horizontal stack layout here and i'm just going to put one thing inside of it i'm going to put a label and i'm going to say text binding to name so we see the name property show up there and it also has the details the location the longitude all this stuff so i'm just going to say name and that all shows up because we've gone ahead and put in that monkey right there which is really cool and we can see we have baboon capuchin red shank duke langer which is really cool so we can spice this up a little bit too so i can put a little padding here of 10 for example that's going to give it a little bit more spacing we could also you know make this a little bit bigger right so i could say font size equals 20. there we go maybe 24 for example there we go and those are going to scale based on your user's accessibility settings as well which is cool all right well we actually have monkeys in a list but we have more data right that we have besides just these monkeys here so we actually have and what i can do is copy and paste the models that are in that readme into our xaml here so i'm just going to go ahead and copy and paste those in and all this does is give me not only the name but it's also going to give me the image the location and we could add the other properties as well if we wanted to there too but now what this is going to enable me to do is you know come in and i could do not only the name i could also do the location for example and now we have a location in here and i could give something like a spacing of 10 for example and maybe make this 10. so now we see you know baboon africa and asia central and south america we kind of get the picture here is that we have our monkeys we also have this here we could change this to i don't know a vertical stack layout for example and now we have our baboon and then we have our monkeys there which is quite nice so uh that's looking pretty okay maybe i'd make this a little bit bigger there and maybe make this a little bit smaller now that we're stacking it this way but hey we got our monkeys which is quite nice that's cool and i like that a lot so we have this right here and we're totally good to go well we also want to add those images right so let's add that image in there now we have the monkey data which is right here but we need to put you know we need to put that image to the left of the names so what we're going to do is we're actually going to wrap this vertical stack layout in a horizontal stack layout all right so i'm going to go ahead and put that here there we go so if you think about it i'm going to have a horizontal so we have an image and then this stack layout to the side which is stacking those items so now what i'm going to do here is i'm going to put in an image i'm going to give it a source a binding here to image i'm going to also give it a height request of 100 a width request of a hundred and then an aspect of aspect fill there's a bunch of different aspects including fill fit so there might be some spacing you know in that hundred hundred based on the aspect center which means put in the center and then fill which is just like fill it in general but i like aspect fill because that keeps the correct um dimensions for me there and there we go we have our monkeys which is pretty rad and of course i could do something like put in some padding of 10 for example and now we have our monkeys right here side by side our rm our text if we wanted to we could also maybe put in a vertical option of center i want to kind of scroll here there's horizontal and vertical options and what that does is it says hey you know i have this space next to this monkey how do you want me to fill it so here i could say start for example it's going to put at the top i could go down here and say end and that's going to put at the end there we go or i could put it in the center which is cool that's nice as well now this is looking actually really really good i like this this is going to enable us to have not only a vertical stack layout here but also two labels inside of it now if i wanted to i could also set up a single label that binds to multiple properties so if i if i actually wanted this to be you know more of a horizontal stack layout here and i wanted this to you know all these things to be centered along the lines i could i could do two labels it would be more beneficial to do a single label so this is where multi-bindings come in that are really cool so i'm going to say label all right and i'm going to actually do open close which enables me to access other properties here so i'm going to say actually label dot text all right and inside of here instead of doing a single binding i'm going to do something called a multi a multi multi binding there we go and i'm going to give this thing a string format so this actually is going to bind to multiple strings and here it has a sort of a special syntax but it's going to say put 0 here i'm going to do a pipe and then one sort of like normal string formatting that you would do with c sharp and then what i'm going to do now is do two bindings and the first one i'm going to say path to name and then a binding here to path of low location perfect i'm going to hit save and now what we see is that we have our baboon and our information here about where they're located so that's quite nice and if i wanted to i could of course say vertical options center that's going to center it there now we are seeing that this is looking pretty close right and there's no spacing between these two so i might want to put a spacing of of 10. so it's kind of up to you how do you want to create your ui right do you want this to be that horizontal uh stack layout do you want it to be just one item and do multiple bindings i wanted to show both of these off because every application is different and you may think oh i have two labels side by side i need to stack those well no if they're going to be the same like we see here and they're going to be the same size you could actually use this multi binding and that's going to cut down dramatically on the number of controls that you have inside of your application now i'm just going to go ahead and back this all out let's back it all out here i actually prefer this horizontal stack layout just in general maybe not that one or the vertical stack layout there you go that one looks really good so i really like that and see how cool that was that i could back that out immediately now i also want to show that you know we have this padding inside of the stack layout we could additionally get rid of that if we wanted to here and add let's say spacing of you know 10 hit save if i put in you know 30 you're going to see this move over so you have the option of how you want to kind of lay this out based on how many controls you have in a stack layout now there is also just a normal stack layout if you're coming from xamarin forms you're like oh what are these horizontal and vertical stack layouts those are new fully optimized stack layouts specific to one operation which is horizontal or vertical so you definitely want to use those if that's the case but i also want to point out what's really cool right is that i basically came in and i just ran the application in debug and with xaml hot reload and how reload here i just wrote code hit save and it updated automatically so that's really really productive here inside of visual studio 2022 when writing these applications i built an entire ui things like that now i will say you can also add more things in here right so if i was to add here like say duke 2 we have another duke if we did duke 3 it's going to add a key on something so we're going to add those there keep adding dukes here dukes here there we go and i'm going to add one more so i can show you what's really cool about this too is that built in to the collection view is automatically this scroll view so i didn't need to wrap my collection view into a scroll view because it already is aware that content is going to scroll inside of this here so if you know if i was to come in and say you know height request of 150 i guess 15 would be small say you know 100 there we go we can see that i'm scrolling through those monkeys there it's very aware of its height inside of this collection view we're going to fill it up of course and and scroll through there too now the other thing that we can do of course is come in and run this exact same application over on windows so i'm just going to go ahead here and hit windows i'm going to hit debug on my machine this is now going to compile up our windows application all right and then what this is going to enable me to do is come in and deploy locally on my machine so again we're going to go through this first debug compilation it's bundling up our assets and it's going to go from there the nice thing about windows too is there's a bunch of other things that you have such as a profiler and memory usage you'll see these diagnostic tools pop up inside of here that's pretty cool which i like so let's go ahead and get this booted up now i'm on a wide screen so you're actually going to see it open pretty wide there's our same exact application right if i go ahead and make this smaller we can see i can scroll around we have all of our monkeys right here in our application and sure enough if i came in and i was to add you know another baboon here there we go baboon 2 hit save sure enough we have baboon 2. another feature that's really nifty especially on your wide screen or on multiple monitors is something that's called xaml live preview so i'm just going to pin this here i'm actually going to get rid of my solution explorer and i can come in and say oh you know what let me just make this the full the full screen of it right here's our monkeys so it's a preview so i can't interact with it however what i can do is i can come in and like add you know yet another monkey in here hit save and we see it updates in real time it's a live visualization of my application it also gives me things like grid lines that i can add inside of here which is really cool i can also hover look at this i can hover over the elements and it'll directly navigate to that item that's so cool right look at that that's really cool if you don't want to have the live preview open you can actually come over to a live visual tree that's really neat and this is going to show you all of the different items inside of your application so this is showing me everything inside the collection view jumps around to the collection view and you can easily get in and out of the different items which is really cool i mean that's one of my favorite features is productivity built right into visual studio 2022 it's going to give you all that stuff right away which i absolutely love so so cool i get all that stuff immediately super productive being able to deploy and there you go we just built our very first application uh putting some monkeys on the screen and what i want to show you here too is that is that the startup and how this happened was this sort of startup here this startup is this builder you're going to see this in every file new project and what i did is actually register the first page as a singleton you don't have to do this but you're going to see why i do as we go through this workshop which is really neat but but we just built an entire thing an entire application right here by coming in and putting in all this data into a list specking it out all with ever ever having to hit stop we're just debugging our application and we're super productive there all right now that we've built our very first application all using xaml and some hard-coded data the next part that we want to investigate is mvvm and data binding this is a core part of building native cross-platform applications with donna maui and if you've come from a wpf or xamarin forms or avalonia or uno background or any of the different xaml platforms you're going to feel right at home but there's a bunch of new libraries that really streamline this process that we're going to take a look at today but if you are just getting started and don't know anything about mvvm or model view view model i'm going to walk you through all of the basics before we jump into the code so let's go ahead and check it out so the first thing that i want to talk about is mvvm or model view view model and this is an architecture pattern to sort of separate your concerns of your code so if we think about it we just created a view and this is how we want to display our information our view could be c sharp with our views that we've created or inside of xaml now this is usually just a bunch of controls and layouts and ideally it doesn't really know about where the data is coming from it doesn't care if the data is coming from a database it doesn't care actually what the database is at all or the data types it just wants to display data in a specific way now that is our view but the view model you can think of it as the code behind for our view and this is telling the page what to display the view knows how to display data but it doesn't necessarily know what to display so the view model is going to control the flow of interaction it is going to do two-way back-and-forth updates of what to display and when things change notify the view that things need to be updated the view will also notify the view model when events happen for example when a button is clicked now our view model also ideally probably doesn't know where the data is coming from it just knows what to display and that's where our model comes in and you can think of this as our business objects our data logic or our main types now sometimes developers may call a restful service call or database directly from the view model but more specifically they'll probably be using some sort of service like a database service or a web service in our application we're going to create a monkey service and that monkey service is going to get the data or the model if you will and return it to our view model and this is nice because now our model can be tested our view model can be tested and our view is just sitting there ready to display that beautiful beautiful information and again this is just an architecture pattern just like mvc model view controller or mvu model view update or architectural patterns the real beauty of it is when things all come together and specifically with an mvvm data binding framework and that is where done maui comes in because our view knows how to display information our view knows what to display and that is where the data binding process in don and maui can bind those two things together and automatically notify each other when things update so there's this glue that really puts things together now let's see what this looks like now the core of it is something called i notify property changed and this is how we notify our user interface from our view model when things update now it is a bunch of code here and we're going to see the verbose version and also the short version when we go into actually creating the code in our workshop but i want to show you the full version here so let's say we have a user view model and we have this method that we can call called on property changed you can tell here that it's taking in a string which means this is the property that we want to notify the user interface for that something has changed now done maui is going to be linking into that event that property changed event handler to make sure that when something is triggered it knows to go update the ui so here for example we could create a property called first name and whenever we change it we could call on property changed and pass in first name as a string we could also use the name of property which would enable us to pass in first string the actual first name property and that would figure it out automatically now this is the more verbose way of doing it and like i said i'm going to show you a way of doing it in just one line of code but just know that when we set the value of first name when it changes if we're typing into a box we're setting in our code behind it will notify the ui that something has changed and updated we can also set this data binding in our c-sharp code behind so if we want to we can automatically set the binding here of the text property to first name or we can set it more verbosely directly to the user view model so instead of using a hard coded string we can go ahead and reference the view model and the first name property itself but more likely if you're coming and using xaml like we are in this workshop we will use this binding syntax this enables us to do all sorts of fancy things such as converters and string formatting or just do normal data binding like we say here so binding first name enables that label to be aware that there is a property inside of the binding context which is our view model with a property of first name now these bindings are all compiled up so they're super optimized and it'll know to go look for that property and update it now there are a few different methods and modes that you can put different data binding in by default.maui will pick the right thing but you can always manually set it so there's usually one way two way one way to binding and in general like i said you normally don't need to set this because done maui is doing it all for you but of course read the documentation on xaml and data binding to learn a lot more but this is a good example where here entry we the user may be typing it into a box but also we might be setting that property from our code behind so we want to weigh our view can update our view model and our view model can update our view so here for example on our entry when the user enters the first name it will update our code behind automatically whereas our label is just displaying information it can't be updated except for the code behind so that is a one-way data binding now like i said it also handles user events such as clicked item selected and a whole bunch more now over here for example when a button is clicked you can go ahead and register for that clicked event just like i talked about earlier with the entry but the downside here is that you have to write a bunch of this code and you must handle this in the code behind of the page not in the view model you don't want your view model to gaining access specifically to the user controls and the in the from the view you want it to be abstracted through mvvm and that again is where mvvm can come in specifically with something called i command an i command is a commanding interface it's an abstraction of what happens when different events are triggered such as a click event so what's nice about this is that you can implement i command inside of your application or use the one that's built in from don maui and you can create a command which enables you to create and set a method that will be called when it's executed so when the button is called it will check can it be executed and then it will execute it you can also then pass in parameters which is great often this is null because you're not really passing in anything but if you wanted to you could you know pass it all sorts of different information or information from another control now let's first talk about i command because it has three required members that we must implement first thing is can execute this is going to determine whether it should be able to be executed or not and by default it is true but what's also nice is that some controls like buttons can automatically be enabled or disabled of course execute that is going to actually be what is called whenever the event occurs and can execute returns true and then there is this event handler and this can automatically be triggered by your view model that it can be raised to notify the user interface to re-evaluate can execute to enable or disable the ui in response to that now data maui has commands built in so you don't need to actually worry about implementing that interface because it's already there so if you have buttons text cells menus things like that you're going to see a command and a command parameter that you can do data binding to and here's what that would look like let's say that there was an i command in our code called give bonus it needs to be public of course because every property that is doing data binding must be public and then it has a get now over here our button is going to do a binding instead of registering that event to that give bonus command now many many times i like to name my things do the thing command right give bonus command upload command download command to me that's what i just like to call it because the method is usually what i'm going to call which would be you know upload for example so this is really nice because you have that i command you can also set these command parameters like i mentioned earlier so if you want to you can automatically pass different data into it and this is nice if you have a bunch of buttons on the screen often sometimes i have it so i pass it like the url of a page that i want to open and you can go ahead and do that too which is really cool and normally those are just strings that you would pass in but you can also do data binding there to other objects on the page or other properties so let's see a look at a full example here here's a good one where i have my employee view model and i have an i command of give bonus and for example here i'm creating that new command and passing it to different methods to execute the first one is on give bonus and that is going to be what is called whenever things are valid and then also on can give bonus and that is a return true or false if you can give the bonus so this is what a normal implementation would look like and again this is of type t so you can pass it data as well now one of the other things about dot maui is it has compiled bindings i've talked about this earlier this enables compile times checks and other optimizations so on every single content page or if you're inside of a list of objects and items you would set this thing called the data type and pretty much what you're doing is you're giving a hint to the compiler to say i'm going to be doing data binding to this object type here i could just say x data type and i'm going to set it to the view model employee view model and that view model is the name space and we go through the workshop here we'll see how to create those new name spaces and how to do this data type and why it's so important because it's important because if i mis-type something it will tell me an error so it's actually kind of nice and we'll see that in real time so let's go ahead and do that let's get started with now knowing some of the mvvm basics in this application so we can start actually creating a list of monkeys and populating that inside of our user interface instead of hard coding that data so let's go ahead and take a look all right this is probably my favorite section of the entire workshop i mean all right all of them are pretty much my favorite section but this one is really cool because i do love mvvm and data binding when it works directly with xaml i just really really enjoy it it's very reminiscent of if you're coming from razer for example and you're doing different razer bindings but there's some magical stuff that can happen in xaml so not too far away but a little bit different syntactical sugar so let's go ahead and now actually change this monkey application so we pull data from the internet and then actually put this directly into the collection view alright so we have our monkey application which is what i showed earlier we have a bunch of monkeys here we can see the live visual trees coming up if you have this of course you're going to want to go ahead and stop debugging because we're going to start writing a bunch of c sharp code directly into our view models and that's sort of the first part is this view model this code behind and this this is sort of an abstraction here now if we zoom in over here we can see that i have three view models we have this monkeys view model which sort of aligns with our our main page here i guess i could call this monkeys page or main view model here but the the default main page with the don and maui app is called main page so i just named it that we also have a monkey details view model you can see both of these are inheriting from this thing called the base view model and it's also a partial class so things can can work together nicely which we'll see here in a bit and then we have this base view model which is empty actually it's just a generic class and i just created these here so again you don't have to create every single class as you're going through the workshop but notice that pretty much a view model aligns with a page and another view model aligns with another page now the reason we like to name these things here is it's easier to align you can of course like do view model first location review page first location it's kind of up to you however you want to inflate the different pages but you can put them directly into this specific project or if you want to do unit testing or something else you could you could take those view models and put them into a separate class library as well so you could really abstract that away fully but for me i just like to put everything in one class here one project it makes it easier now we're gonna use this base view model as the base so when i mean base what i mean is that that everything else will inherit from this so we can add some common properties that every single view model can have so everything has a title or maybe like an is busy property or is not busy which is quite nice so we're going to get going here and we're going to first implement the base of everything that everything has to do with mvvm which is an interface called i notify property changed now i'm going to show you the the classic tried and true way of doing mvvm then i'm going to show you how to do fancy modern mvvm in my opinion but i want to show you how this thing actually works behind the hood so what we have here is an i notify property change and i'm going to go ahead and implement this interface so here we can see that we get this property change event and this specifically is the event that donet maui is registering and signing up for this is a way of saying hey i've changed some code in my code behind and i'm doing some data binding to the user interface dynamic please go update my user interface for me that's really what we want to have come across now what we're going to do is create a method here that any of our view models could call to raise this event because we need to be able to raise and tell don maui when things are happening so i'm going to create a public void of on property changed and we need to pass it a string of name now inside of here visual studio just going ahead and writing all my code for me which is fantastic but this is what it looks like specifically is this property changed which is this event right here it's doing this question mark dot and what that's doing is a null check and what that is saying is is anybody subscribed currently to this event and if so then invoke it it's going to pass itself whatever the view model is and then it's going to give it this new property changed event args that's going to pass in the specific name of the property all right so let's say we have some common properties that we want to to use this new on property change with so let's say we have a bool called is busy and a string called title all right so this is something i have in almost every single one of my applications which what is the title in the top bar and then also is busy i used to show like activity indicators or little spinners for example so what we can do now is notice that these are private so these are the things that i'm going to reference in my code behind over here and we're going to expose a public property and we're always going to use that public property this is sort of our backing field so the first thing i'm going to do is i'm going to do a public bool is busy here and i'm going to do a get i'm going to use fancier syntax for returning is busy and then what i'm going to do is a set and visual studio wants to just return it but i'm not going to let it what we're going to do here is we're going to say is is busy the code behind backing equal to the value so if it's the same value already so we're setting true and we're sending again to true don't do anything because it's already set to the same value else go ahead and assign it so we're just going to assign it to is busy the value and then we're going to say on property changed and now we can pass in the name of the property so it is busy specifically now that's one way of doing it here and again if we walk through this where we're always returning and modifying the backing field so this private boolean the reason we make this public is because the done maui when it's doing that data binding specifically to the user interface and making that connection to the view model needs to be public it needs to be accessible by the user interface itself and additionally that public is what the intellisense will pick up because it needs to be published you need to be able to see that as it's inspecting the different metadata so when we get it it's always going to return as busy just always return that but when we set it check to see if it's the same value and if so return else set it so it was true now it's false and then notify the user interface that that has changed so any of our controls specifically that word data bound to is busy will get notified that that thing has changed now notice that i did put a hard-coded string here there's two ways that we can actually update and get around this the first one is coming in and using the name of this is nice this is one of my favorite features you'll see me use this a lot but name of is exactly the same as that hard coded string name of says give me the string version of this property of this method or whatever it is and this is really really nice so this is cool because now if i rename this and i say is not busy see how it updates both of them there we're not going to do that though we're just going to make it as busy so that is one of the nicest things but it would also be nice if i didn't have to pass this at all so we can do that there's actually a compiler optimizer setting here that i can append onto this onto this here and the on property change which is called caller member name and this is a runtime compiler service and here all we need to do is add that on and then assign it to a default which is which is null here so that's quite nice and what that enables us to do is continue to pass in the string or not so if we don't pass in anything and we just call it the compiler is going to essentially look up at compile time not at runtime and say hey what they're actually meaning here is that they're not passing in anything so get the caller member name out which is is busy pretty cool all right now we can do the same thing for title down here too so if i said public string title there we go get the title and we'll do a set here and we'll do the same thing we'll say if title equals equals value return else title equals value and then on property change so that's that's quite nice now this is quite a little bit of code for every single property but this is is how you would kind of implement it at its raw level there's a lot of different helper libraries out there i have one called mvvm helpers there's um a medium light there's prism there's there's all these different mvvm you know some are frameworks and some are helpers that can give you some simplified methods uh but there's easy ways of of making this smaller which we're going to see here in a few minutes uh cool all right so so far what we have is is busy and tidal but one thing that i like to do in all my applications is i also like to have an is not busy so so many people like to have converters in their application which means hey take this value and convert it to something else it's one of the very powerful features of xaml you could take like a monkey and convert it into i don't know some ordered list or so you know you could you could say take this object and then give me the the first um you know letter of the name for example or you could convert a true to a false or lowercase to capitalize and these are really powerful there's tons inside of the net maui community toolkit which i'll put a link to have these implemented i'm not going to cover them in this but i also like to not use converters if i don't have to in my personal opinion so imagine we wanted to have an is not busy well what would we have to do there's like we could implement it is not busy we'd keep them in sync but really it's just the opposite of his busy so what i could do down here is create a new public bool is not busy i'm going to have it return the opposite of is busy now the quirk here is that we need to notify maui whenever is busy changes to also update is not busy all right so what we can do down here is raise another on property changed this time i'm going to do name of is not busy all right so what this enables me to do is very very easily get up and running by doing mvvm now i have a whole video on mvvm 101 and data binding and all this stuff but this should give you the base here that is happening now if we wanted to now do some data binding right to this title let me show you what that would look like in our code so for example i could now come over into this page and i could say here i could say you know title and i could do a a binding here to the word title and then i could also say you know is visible for example and do a binding to is not busy right so this is how we do data binding based off of those properties and we're going to see this in action once we start to build out our back end of our application and build this new collection view with data binding in mind but this binding syntax is what is the glue right so this is going to find a property called title this is going to find one that is called is not busy and what we've done is aligned the the property so title is a string is visible as a boolean that is how you would put those things together if is visible was a enum for example i would either need to go in and change this to an enum or if i really wanted to decouple it i could do that value converter that we were talking about earlier let's go ahead and back out these changes we don't need to do that there perfect now that is specifically the core of mvvm it is i notify property changed and it is the ability to get and set properties from our code behind and bind them in our user interface and notify it via these on property changed events now the cool part is that you could actually delete all this code so for example imagine you didn't want to write any of this code at all okay you just wanted to i don't know make it look like this that would be pretty nice well if we head over back into this build targets you can see that i've added this nuget package called the community toolkit.mbvm this is part of the net community toolkit and in fact the community toolkit is is a bunch of open source repos on github powered by the community and supported by microsoft and there's one for windows one for donna maui one for net which works on any dotnet application wpf when ui don and maui older xamarin projects all that stuff and then there's a bunch of other ones too so you definitely want to check those all out now the community toolkit.mvvm has some really awesome automagic source generators and source generators enable us to add attributes or little indicators to our code and have the source the code be generated automatically so what we can do here is let's go ahead and comment this out and we'll add that back later is instead of you know coming in here and inheriting and implementing i notify property changed what we can do actually up top is add that as this attribute and i want to show you that as i hover over the intellisense it's going to show me that this attribute that i've added comes from the community toolkit.mvvm.component model which was one of those global usings that i added here so i'd have to add that which is uh pretty awesome and then it's going to tell me that i need to make this a partial class because source generators are going to generate the code for me automatically through a partial class implementation so what this means is that if i go now pull this out into my dependencies and i go into my analyzers we're going to see all of the the different analyzers and source code generators that are here there's one for system text json for the maui controls extension loggers a bunch of stuff and if i pop this down for the mvvm source generators you can see all of the different attributes that will source generate code and here's the i notify property changed and sure enough check this out we have the monkey finder view model base view model so here's a partial class that has been generated for me automatically now this is going to look super duper scary but don't worry it's not that scary because it's source generated and you don't need to touch this ever in fact you shouldn't it tells you don't edit it in fact just don't donate it you can't edit it because it'll generate over itself but what this is going to do is give me an implementation of inotify property change for the base view model and it's going to implement all of that stuff for me so check this out and on property change it's going to give me um different compiler service options right here's what we had earlier that same one that we had in earlier we're also going to have a set property method that's really cool it's going to give me the ability to do on property change it's going to automatically do comparative compare equalizers here you scroll down it's just going to generate all of this code for me automatically all these overrides all these different you know implementations of finely tuned and optimized code that i no longer have to write so if i came in and said public base view model right my little constructor i now would have the on property changed i'd have something called set property which would take in a ref to a isbool and then i could say true for example and that would go ahead and set the property and raise the notification for me automatically so it gives me all of these really really nice capabilities built right in now the ability to use this i'm going to leave that there actually no just so we're going to get rid of that but we'll see what this does now the ability to add the inotify property changed here that's important because um if your base view model isn't inheriting from another class you wouldn't be able to inherit from another class you can only inherit from one class so this i notify property change attribute is a nice thing that just says hey go implement this and do all the nice things for me now that's one option the other option specifically is to use a base class inside of the community toolkit called observable object right and this comes from that component model as well and i'm going to go to the definition and we're going to see that this is even better than adding that attribute because inheriting from that base class will just automatically implement i notify property changed and additionally another one that i don't use very often but can be important for certain applications is i notify property changing so this is actually really neat because now we have all the same methods and it will automatically enable us to go off and use all of these interfaces here and it just gives us all this boilerplate code automatic so that is really really neat that it one gives you these default implementations for your observable object and there's a lot more in the community to look at i'll put show links down below don't worry but it also can do source generation for our properties because you're probably saying james wow you keep talking about this stuff but how are we going to get our public properties back well we're going to add an attribute called observable property there's observable object and observable property there's this whole validation and observable recipient as well but i'm just going to do that cool i'm going to add one over here as well observable property and now i'm going to add back my is busy and i want you to or is not busy and i want you to notice that this is no longer red squiggly at all that's pretty cool because if we come back over into our tool kit we can note that there is this observable property generator and sure enough there is now a monkey finder view model base view model all right and what this has done is automatically generated those properties for me and they're super optimized with caching of the property changed events and again you will never modify this code it does all these global things just for optimizations and making sure it works everywhere but it's amazing and look at this it's going to go in and when it sets is busy it's going to call on property changing set the value and on property change as long as the equality compare is valid same thing for title here which is super cool now on top of that we're able to do other things too because we need to not only trigger that property changed event for is busy but also for is not busy right so what we need to do now is come in and say also notify can change for right i'm going to say name of is not busy boom now the main difference is the generated code has been updated here as it's still open it's just regenerating itself i'm not compiling i'm doing anything i don't have to save it just does it but notice here that after i specifically call is busy we get a property change for both is busy and is not busy which is pretty awesome so it automatically handles that for us without having to worry about it at all 100 now this library can not only handle simple properties but it's also going to do um commands as well and one thing that's kind of crazy is actually if i scroll up here you can see that it's really well documented right here so you can actually see the optimizations automatically that it's giving you and it tells you exactly what to do it's kind of kind of ridiculous and awesome at the same time but that's it we've now reduced all of our source code to a single page that we can see and it's the same implementation so here if i do this dot notice that i have a lowercase title which you can see and that title as well so that was generated and that's what we would do the data binding to is that title that we have and that's nice so now in just literally a few lines of code we've created properties we've created inverses of the is busy and we're ready to do some data binding there which is oh so cool and that right there is some base of mvvm that we're going to put into our application all right now now that we have our base view model up we're going to start to implement some things into our monkeys view model so this is what is going to be doing data binding specifically to that user interface so what that means is that we're going to need to have some sort of way of getting monkeys from the internet and you could put that code directly into this view model but whenever i'm doing database access or file access or web service calls i like to have something called a service and i'm going to have a monkey service here now this monkey service is going to implement any of the methods that i need for my application to go and get monkeys from the internet now you can make this an interface as well so if you want to inject things and do a bunch of stuff you can also have an imonkey service so you can totally do that for this what we're going to do is actually just create one one method called public async task and what we're going to do is return a list of monkey here we're going to say get monkeys there we go and return something right at this point so let's let's let's return well maybe not i guess we'll return null for now right so we have this this monkey so our view model instead of calling to make a web request we'll just go ahead and do it here okay so here's what we're going to do is instead of you know returning null i'm just going to create a list here uh of monkey looks pretty good and i'm going to say equals new there we go and we're going to use some fancier syntax we can just do that that's cool and we'll just return this monkey list perfect so now we have a monkey list kind of a backing field we're just going to do sort of an in-memory cache here for our monkey list and then we're going to go and now figure out how to implement that http request so for http what we're going to do is use the built-in http client and this is built into.net and what happens is when you run this on ios android mac it'll use the underlying systems to make those restful service calls which is quite nice so all of your tls and ssl and all that stuff will work and what we're going to do is we're just going to create a constructor here for our monkey service and we're going to create a new http client right so here we just need one we're going to reuse it that way it can do caching and do all this stuff it's all built in you don't need to worry about disposing of it doing anything like that because the http client is super optimized for mobile all right now the next thing that we want to do is use this restful service okay so what we're going to do is we're going to come in i'm going to say if monkeylist dot count is greater than 0 i'm going to return the monkey list all right so this is going to be my lightweight data cache and so if i jam on the button say get monkeys get monkeys get monkeys get monkeys what i'm going to do is just return the same list of monkeys every time if it has more than zero but if it doesn't let's go ahead and call off and get monkeys from the internet so if you remember we have a monkey service on the internet so if i go over into the the the repo here we remember that over on the display data part of the workshop i told you that there was this monkey's json file here right so if i go ahead and copy that link and i open that up right here's this this monkey data that came in so what we want to do is use that so i'm going to say var url equals my website there we go so montemagno.com which is my blog you can totally check it out and it's going to be the monkeys.json now i'm not actually hosting that on my my website so if you were to go in specifically again you can see up here that i'm hosting that file on on github so it just redirects it which is quite nice okay so we have our url and now we're going to do is we're going to use the http client to get a response and look at this it just automatically gets it now we're going to wait on that response so it's asynchronous it's going to go back on a background task it's going to go pull that data so it's not going to lock up our ui at all and we're going to get that asynchronously now i want to note here that while visual studio just filled in everything for me because it's so smart we can do gets we can do puts we can do posts we can do all that some asynchronously [Music] restful service calls right so it's all built in so if you need to call your asp.net core web api or another web api you can do that you can also get something called get string async and this is what i usually have done in the past but in this instance we are actually going to use the new json deserializer part of.net and what that is going to do is actually be a helper method on our response so our response is going to get this generic get so it's going to get stuff it's going to have information it's going to have content that is being returned and also a status code so i'm going to say if response dot is successful status code then that means we got it we hit the internet and we can now read that data so this is really neat this is like super duper cool so i'm going to say monkey list oops monkey list equals i'm going to await the response dot content now the content here is from that get from the internet and that's going to have our string data our json data in there but i've added specifically into here the system text json which is part of.net and that has an extension method called read from uh sorry read from json async okay and this is going to specifically use the system net http json we can say hey i want a list of monkey back here all right so we add this little using statement up top here systemnet http json and here this is going to read it from the json and it's going to automatically deserialize that string and bring it back as a list of monkeys which is very very cool so that automatically comes in there and of course the intellisense picks that up which is oh so cool now i do want to mention here for some reason you're doing this and you have maybe a vpn on or maybe you have a some work requirements where you can't run this http gad or you're having some emulator issues i do want to note that inside of the specific module that you're going through on github i've added a little helper here to read the monkey data from a json file that's embedded inside the application so if you take a look inside of those resources raw i've put that monkeydata.json here too and that's going to be embedded into the application at runtime and what i'm doing here is i'm i'm using don and maui it has this file system helper and the file system helper is specific to don and maui apps to read and write things from the application layers like ios android mac and windows if you just want to write to the file system you can do system io just normal reads and writes all day but this is going to open up a package file because we've embedded that package it's going to read it with a stream reader and then deserialize it with the built-in system text json deserializer so for some reason you can't get access to the internet wherever you're at although you're streaming this video but maybe again you have a weird vpn issue you can just put this in there and that's quite nice so that's cool all right so now what we want to do is we have our method set up right that's not very a lot of code it's just our get monkey service and here we're going to go ahead and make that restful call is success status code and go get it so now we're going to do is we're going to head back over to our monkeys view model which is empty okay now this is inheriting from base view model so we have all that mvvm goodness in here not in fact if i did public monkeys view model we can see this dot title dot is busy those properties are there which is quite nice uh in fact we can set that we said title equals monkey finder for example and now we have monkey finder there now we're going to call into that service but we need to give the collection view some sort of data type to do data binding to for that list of monkeys now here i've added just an array because i'm hard coding the data but ideally what you would use as some sort of list or ideally on top of that something called an observable collection now an observable collection is an observable collection it's an observable array or an observable list and it has built-in notifications when things are added or removed so if i come in and say public observable collection of monkeys look at that so cool we can just do a get here and then when we new this up we'll just say new like that we're going to create an observable collection of monkeys and we're just going to create a new one now i don't need to add observable property here and i don't need to create a lowercase one because i'm never going to raise a property change notification on the observable collection i'm just going to add and remove items into the observable collection and it's going to raise the notifications to don o'malley i'm not going to the observable collection is but when i set this title that ideally would you know raise that notification up okay now we're going to use that service so let's add a using statement up top here so we're going to do using monkeyfinder.services all right and now what we need to do is get access to that service and we're going to do that by creating a monkey service there we go cool and i just love it so good and we're going to inject that into the view model here so we're going to talk about dependency injection and automatic dependency resolution but what we want to have happen is when we create the monkey's view model we can tell it what it needs to be aware about right what does it need to know to [Music] get everything that it needs it's dependencies what is needed to run this service so visual studio is so smart filling in what i need i'm going to pass it a monkey service and then it's going to set that automatically and don maui has a built-in dependency service and injection service that will register this and we'll talk about that here in a second all right so now what we need to do is specifically create a method that will call into that service so it's going to be an async task of get monkeys async all right we have our get monkeys async that's looking good and this is how i like to code this up so the first thing we're going to do is check to see is busy so am i doing something i'm already getting some monkeys from the internet then just return so if someone jams on the button right there's no need to to do it twice and then what i'm going to do is i'm going to come in and do a try catch um let's catch an exception there we go and then i'm going to do a finally here there we go try catch finally so try says try to do stuff in here and then catch enables you to catch if an exception occurs so imagine you went and tried to make that restful service club you don't have internet well that's going to throw an exception because you don't have internet that would go ahead and go into this block and you could maybe pop up a notification finally is a block that always gets called at the end of a successful or a not successful and unsuccessful if you will call in the try block so after try or after the catch finally we'll always get called so it's a nice way of saying finally always no matter what do this so the first thing i could do in the try is set is busy to true and at the end i can say is busy equals equals false all right so now we have is busy is biz equals false and now we know that's always going to get called no matter what so now underneath our is busy true that can notify the ui that maybe to do an activity indicator we're going to say var monkeys equals we're going to await on that monkey service and say get monkeys and just like that we're going to have our list of monkeys automatically now at this point we can do one of two things we could like created a new observable collection and put these monkeys and then raise that notification but i'm just going to add all those monkeys to the list so the first thing i'll do is i'm going to say if monkeys.count does not equal zero for some reason you know we've already filled the the list up we're just going to do monkeys.clear so that we would get new monkeys into the list so i kind of like to do this check because why call clear if you don't need to call clear and i don't know what clear is doing under the hood maybe it's already doing it but i like to do that in my code just to be kind of extra sure that i'm not calling clear for no good reason and then i'm going to say for each var monkey in monkeys let's add them to the observable collection here there we go now be aware though that the observable collection here i'm going to go through this tight loop and i'm going to add all these monkeys to this observable collection and every single time it's going to raise an event so if you have thousands of items you may not want to do this you might actually want to create a new list or a new observable collection and raise that event or look into some helper libraries that have things like observable range collections that will do batch um adding as well for example my mvvm helpers library which i'll link to up here i have a whole video on it that has some nice helper things in there as well now i think it done at seven they're looking at adding a few methods here so be tuned if you're tuning into this after done at seven or down at eight there might be some new methods on here right instead of just add and insert there might be an ad range for example this would be kind of cool all right now we're going to do is handle this exception so if something does go wrong we want to probably figure out what's going on so we can use debug which would output something into debug for us automatically and we're just going to write line and let's just put put the exception there that's good enough for me but we might want to notify our user so i can come in and say a wait and you can either say shell.current or you could say app dot current dot main page to access the main page i prefer shell in case we have multiple windows i'm gonna say shell dot current dot display now i have the ability to display let me pull this up a little bit an action sheet an alert or a prompt to do some data entry now some people may not like what i'm doing here and i totally get it which is i'm putting you know i'm accessing my ui directly into my view model so you might want to have an interface for example that would do these things for you inject that in totally handle this is a workshop so i'm not going to do that extra stuff there but if you really want to abstract it go for it i'm going to display alert and i'll say error here we're going to give it a message we'll say you know unable to get monkeys and then you should not do this but let's output the message of the error and then say okay there we go so it'll pop up an alert a native alert dialog for us and we'll get our monkeys and that's it then we're good to go so we're now notifying our users you could also do string translations there with res x files all that stuff check out the documentation i'm not going to handle that in the workshop but it'll be there okay now one thing that you may have noticed is that this is private so how am i going to call get monkeys from our user interface right how am i going to maybe click on a button or do pull to refresh and call this get monkeys async because what we want to do of course is get those monkeys from the service make sure we have it add it in there as long as you don't have anything here or handle an exception accordingly well like we said earlier during the presentation part there's a thing called a command so what i could do up here is i could create a public command okay of get monkeys command here and i could do a get and this command is coming from dotnet maui all right so if i peek in here we can see that dot net maui has an implementation of i command additionally not only does i command have it my mvvm helpers has it and also the toolkit has one too but let me show you how you would normally do this so here what i would do is i would say get monkeys command and i would pass in or create a new command and here this is asynchronous so this only takes actions so if i had a void of do stuff for example i could i could pass in do stuff here right i could do that but since this is asynchronous i'm going to have to do a little magic here which is asynchronously call the get monkeys async here cool and that's how i create a new command now on this command i could invoke i can do can execute can execute change i can pass in all these different things automatically but yes you guessed it the toolkit is going to handle this for us so we can throw this all away get out of here we don't want none of that because what we want to do is turn this method into a command so what i can do is come in and say i command and this i command you guessed it is coming from the mvvm toolkit in the input namespace which means check this out if i come over here and i go into my dependencies and i come back into my source generators we're going to see i command and sure enough get monkeys async is created for me and look at this we can see that i have an async or relay command that ideally is what is coming from the community toolkit and that is going to give us everything we need this new get monkeys command it's chopped off async it knows to if you add async or you don't add async it's smart enough to figure that out and it's going to create this new thing for us automatically which is really cool again that's available on all.net apps which is awesome so what's amazing here is i can now say get monkeys command and i can do the same thing i can do can be cancelled i can cancel the command i can i can do can execute can't execute changed four i can execute it asynchronously i could get the execution task i can there's a there's tons of is it running this is amazing this is new it's so cool there's all the different changes and all this stuff it's so good so it gives you all that stuff automatically and additionally if you did have just a void of do stuff here right just like that and i put an i command on that and we go back into that code that was generated um here let me go ahead and oop it's going to be in this one just generated it on the fly we can see that this one is now do stuff command and it's an i relay command it's smart enough to know if it's asynchronous or not which is so cool i just love it ah so good alright we're not gonna do do stuff okay there we go okay so now we have all that magic stuff happening we have our view model right everything is like looking pretty spectacular i love this like look at this it's very minimal code all the code to do the the business logic and the restful service calls are in our service it's over there being happy and our view model is just getting code and saying hey just display this stuff it's getting in the monkeys and in the code is saying just do a data binding to this monkey's list so now what we want to do before we build the user interface is do some linking together of the view model the monkey service and the page itself so here's what we're going to do is we're going to register those dependencies okay and we're specifically going to do that if we go and drop this down into our maui program if you remember in the first part i said that i was registering the main page i'm registering the main page with the built-in dependency service the iservice collection because shell itself and the navigation service and the inflation service and the creation service will not only be able to create the page but if you register that page with the dependency service it will automatically know to grab that page from it and all of its dependencies so what i could do here is i could say builder dot services dot add singleton and you can add not only a singleton you can add a transient as well a singleton says create this once and just keep it around for me and return that same instance a transient will create another one every time you called to get a new one and here we're gonna only ever have one main page so only ever create one in the singleton um totally up to you i'm gonna do add singleton and i'm going to do a monkey service here monkey service just like that i'm going to go ahead and bring in my namespace and then i'm going to say builder dot services dot add singleton again of our monkeys view model all right and again up here we have our our different views and our services that are brought in automatically with our using statements and now we've registered those together right so our our page we'll use our view model which will use our service not actually no matter what order you put these in because it doesn't matter until after but i sort of like to put my services and then my view models and my pages that's just me i don't know it just kind of makes it easier and i don't know that's just how i like to do it now the last thing we need to do is kind of link together this page in this this view model so what i'm going to do is on the main page i'm going to do a drop down here for the main pages xaml cs and what i'm going to do is i'm going to say hey page in your constructor you're going to use a monkey's view model i'm just going to say view model and i'm going to set something called the binding context the binding context is similar if you had done a data context on like wpf or uwp or something like that but it's just a different name for it it's the same thing it says this is the context for this page and because i've registered the page i've registered the view model and the service everything will trickle down so if i add a break point here let's go ahead and start to debug this up see if it compiles that'll be good i go into my monkey's view model i add a break point here and then we take a look what we should get is that our main page gets our view model and our view model gets our service so here are applications oh here we go boom view model we have our service there it is amazing there's no monkeys in the list boom we get a view model automatically for us now we could create one there but we're not going to because it's just right here automatically and boom we have our application ready to go amazing and now what we can do is start to build our user interface and that's sort of the next part here so let's go ahead and start to do that so i'm going to come in and the first thing i want to do is associate this view with the view model so i'm going to say xmlns view model very similar to what we did earlier here i'm going to say here's our namespace review model and just like we assigned if we remember the collection view data type for the item i'm going to say hey the data type for this page is my view model dot monkey's view model it then allows me to do things like set a binding of the title here okay that's pretty nice and now notice that when i save that the title it automatically updated it to monkey finder just like that it automatically knew to go ahead and do that so that's really cool right we've associated it here so we're gonna get some intellisense here and then also we're gonna now be able to update this was really cool so all right things are looking okay what we're gonna do now that we have our data type and our view model what we're gonna do is we're gonna change this collection view to read from that that that view model we're going to make a restful service call to do that now how we're going to do that is that we are going to use all of those different properties and those commands to create a list your listview a collection view and underneath it a button that we can press that will invoke that command right get that monkeys from the internet and then put them into the list automatically and that's going to be all done through mvvm data binding and the collection view and whenever we add those monkeys into the list it's going to tell the collection view go add these monkeys and we're also going to create a nice beautiful cell over there so those monkeys look good but what we've done so far is added all the source code right now we're just on the user interface and making it look pretty so let's go ahead and now make that data binding stuff a reality alright so the first thing that we want to do is clear out our page we want to get rid of any of that stuff in the collection view we're going to put a new one in there so we can get rid of these these monkeys goodbye monkeys we're just going to collapse that down control that out and delete it and now we're back at a blank slate now we are going to go ahead and create a page that looks a little bit like this i'm going to bring this over we're going to have a collection view up top with these nice little cards over here with a search button and a find closest and this is basically going to be two rows and two columns so this collection view in the first row and then two columns with this search and find closest that's what we're going to build okay so the first thing we need to do is figure out how are we going to get those things into a grid of columns and rows i'm glad you asked because we actually have a grid layout which has columns and rows so we're going to do these column definitions and i'll explain what this means but you can think of it as you can define them in ratios or automatically say size this column or row to however big the controls are and the syntax specifically is either auto a number or the star syntax and i'm going to do star star here and star star is the de facto of of sort of fill the rest of the space or as much space as possible to a ratio so this star star would mean use fifty percent fifty percent because they're equally weighted if i added another star this would be thirty three thirty three thirty three point three through three you know definitely right but i could also do a star star auto and this would say make basically the second so this is index zero so you have zero one two here so make that last column as big as it needs to be and then equally divide the first two parts up there now we're going to have two columns because we have two buttons at the bottom and what we're then going to do is put a little bit of column spacing in between them so let's put in 5 there so it's going to give a little bit of space between the columns now we're going to do row definitions as well and the first one is that collection view up top so i'm going to put a star i'm going to say auto now we don't need to define a row spacing at all because the default is zero so it's up to you if you want to see it in the code put it there you can do it right you can say row spacing zero but that is the default so you'd be good to go okay so now we're going to do is we're going to put in a collection view and we're also going to put in a button but let me show you what that would look like so we're going to have a collection view and a button on the bottom left so let me do a collection view here and i'm going to do a background color of pink just so you can kind of get a good representation here so i'm just going to close it open and close that up and notice that the collection view is filling this in first 50 of the content page because we've assigned it by default to zero zero so everything is index zero zero base zero zero so since the collection view is gonna be at zero zero i don't need to set where it needs to be but i do need to set it for how many columns it needs to span so if i come in to this and i say grid dot you can think of this as sort of an extension property off of it so it knows that hey i'm inside of a grid i can assign the column or the row or the spans so i can say column span two and hit save and now notice that it fills both of them now this is pretty cool and what we might be noticing is that it is filling the entire page and you're saying well james you have two rows well i do have two rows but notice here that i've assigned that to auto if i was to assign this to a hundred we can see that now this moves up a hundred right since we assigned it to auto though here it's gonna until something's in there right it's not gonna do anything so for example if we came down here and we we put in a button you know button i said text get monkeys and we go ahead and close that off we can hit save now notice this get monkeys is filling the whole thing right that's crazy but i could assign that to be in the first columns and column zero the first one and that's the defaults i need to do in there but i could then say grid dot row one right and that's going to move it to the bottom left which is pretty cool and i could even give it a little bit of spacing here if i wanted to so i could say margin 8 for example and that's going to move it and say push me away 8 density pixels away from everything and that's quite nice so i can actually give it a little bit of breathing room there's padding which is inside of it so if i added a padding here to the grid and i said padding equals 10 you see that everything moves in because it's inside the layout whereas the margin is get away from you right get away basically so uh we don't want any padding there because we have the collection view but we do want that button to have a little bit of room to breathe all right let's focus on this collection view here and what i'm going to do now is we can we can you know set this like transparent background so we don't need that there or you could just leave it off but i'm going to say items source and remember previous module we hard coded that data now what we're going to do is we're going to say binding to monkeys there's our monkeys that's our list of items and then what i'm going to do is i'm going to say selection mode there's selected item selection changed there's commands that's kind of cool selection changed command you could do a data binding specifically whenever an item is selected or unselected we're going to use tap events and we're going to get to that later and i'll tell you why but here i'm just going to say none but you could do multiple or single you're kind of in control there which is nice all right we have our collection view it's still blank is what you're saying james you're right um it is still blank that is correct uh so let's go ahead and and make this uh monkey do something we don't have any monkeys because it's empty but let's go ahead and give the monkey something to look at right so when we when we call it to get the monkey so i'm going to say collection view dot item template there we go item template and of course we're going to fill this again with a data template so i'm going to come in i'm going to say data template and this is going to be another type of model of monkey so just like we did before nothing crazy there now if you remember we're going to have that nice little card view and actually in our app xaml i've defined a few styles here automatically for us so we can see i have a card view a frame and this button outline as well we'll kind of get to those in a little bit but we're going to put some um some of these in there and use these styles and then later we're gonna tweak them and fine-tune them so i'm gonna go ahead and say we'll make the entirety of this one big grid i'm gonna give that a padding of 10 because we don't want that that frame to kind of fill the entirety of it we want to be a little bit inset and then what i'm going to do is i'm going to do a little frame here and do a padding of zero inside of it oh sorry a height a request of of let's say 125 and then go ahead and open that up again i don't have any items so it's kind of hard to visualize here but let's just go ahead and put some stuff in it so i'm going to put a let's just put an image in here maybe just for good measure i don't know well let's just put like a label in here right so let's do label a text property of binding to name all right so we're going to come back and fix this up but let's let's get some data to visualize because it's not quite fun looking at this blank screen so let's actually go ahead and implement this button right so let's go ahead and and and put this button in here and then we're gonna go fix this up a little bit uh as well so let's go and do that so we have our get monkeys that's cool bring this up top a little bit and now we could do is we could do some other data binding so we'll say command so whenever i tap on it let's do a binding to get monkeys command there we go and that's again that's coming from this get monkeys async and we marked it with the i command there and then what we're going to do is we're going to say is enabled i'm going to do a binding here to is not busy the reason i'm doing that is because if it's busy then i don't want it to be enabled but if it is not busy which it currently is you know not busy it's not doing anything then just leave it alone now we could do is we could put in like a little activity indicator maybe in the center of the screen when things are loading too whenever we tap that so we can do that we'll put an activity indicator kind of like a progress bar and this is cool i can say is visible right so kind of like is enabled i can say binding to is is busy and then i can do is running a binding to is busy okay and then what i'm going to do is i'm going to put it in the center i'm going to say or fill it you know horizontally and vertically let's go ahead and put that in the center and now this is kind of cool i'm going to kind of overlay this control on top of everything so i'm going to say grid dot row span 2 and grid dot column span 2 as well now there is also a z index that you could assign things as well and i'm not super duper familiar with the z index there's a new thing in down in maui but it's here um but let's go ahead and click on that button look at that boom we just got some stuff coming in and just like that we got some monkeys coming in look at that boom we got baboon we got capuchin monkey that's pretty cool right so we actually have some data coming in and when i tap it it comes in right away which is really really cool so now we can start working on this data all right so we got our frame in here that's looking pretty cool but let's actually do something a little bit i don't know a little bit nicer right so we have a frame let's then put in maybe a grid inside this because we kind of want to have that that look and feel like we had earlier which was um an image on the left and then two things on the right maybe i shouldn't have deleted that code but let's go ahead and put this in so we're gonna put a image in here and we'll say aspect let's go ahead and delete this here aspect aspect fill i'm going to say source binding to an image let's do with request 125. uh height request of 125 just because we don't know what the image is going to be there we go i guess i could i'm just putting that inside there so it's right in the middle but okay let's put this in a grid so we're going to do grid again all right and we're gonna do a padding of zero let's do a column uh definition of 125 and star perfect now we can put that monkey in there and now our monkeys are over here but they're a little cut off because this frame has a bunch of padding so let's go ahead and do a padding of zero there we go now our monkeys are looking a little bit better inside of this collection view which is rad all right now the other thing we'll do here is we're going to put a little uh vertical stack layout where is a grid.column span or column one all right we're going to give it a little bit of padding maybe of 10. let's do i don't want this jumps back over all the time we'll put this vertical option center and then let's put in some labels okay so we're going to do a label i'll say text let's do that binding to name again there we go and then another label and text binding to the location just like we had earlier and sure enough we're going to get our info in there now we also have some predefined styles here for labels so some preset medium label small label micro label so we can use those and we can spice this up a little bit so i could say for example let's go ahead and minimize this down a little bit we don't need that let's put this over here since that's going to work a little bit better we can do a style and we can say static resource of let's say large label and then we'll do another one of medium label hit save there now sometimes these styles they're not going to work with hot reload of how they're looking up up so we're gonna have to reload the application here sometimes it works sometimes it doesn't i'm not positive again because hot reload can kind of get into that state where it's maybe hasn't indexed those um so that could be something that's happening there so we don't see those update here but why don't we go ahead and add the other styles that we've defined so for example on our frame we actually have a style of the static resource of frame or card view and then on this button down here we're also going to use a style and we're going to say static resource of our button outline so not showing up there but i'm just going to hit this little refresh button and that's going to kind of stop everything reboot it deploy it but what i want to show you is that these styles that we're going to get to in a future episode are just defining different values over there so here i've just set the background color border color height radius things like that so that way you don't have to repeat them over and over and over again which is quite nice so here's our get monkeys so that is nicely themed we have a nice little spinner and boom we have our beautiful monkeys in our list and they have different stylings on them that are coming in just like that which is pretty cool looks pretty good the card view and the frame not bad right it looks pretty good so there we have it that's our very first part of actually building this app with mvm mvvm right reminder here let's rewind really quick of what we did is we went in we created a base view model we have ours busy our is not busy our title properties we then went ahead and created a monkey service which went off to the internet it went off and pulled down that data if i click on this button let's go ahead and refresh it one more time since it'll be fresh it's going to go off to the internet pull down that data with our http client and put it into the list which is pretty rad so let's go ahead and pull that up get monkeys boom right so we have this response it's a power here we have this nice little thing coming down with our base we have our content we have a whole like you know header thing that's coming in a bunch of stuff coming in and sure enough if i had a break point here we get our list of monkeys here's all of our monkeys right which is really cool and all of our monkeys and they're coming back into our list right here this collection view all stylized and that's happening because our view model is now being data bound to our main page and we can see the data binding here we're setting the type for intellisense and also compiled bindings which means they're going to be more efficient and then we've stylized our collection view right here with with a grid so we have a little padding here we have a frame inside that is a grid that's going to have a first column and then a column that fills the rest of it an image which is our image of monkey and then a vertical stack layout here that's going to go and stack our monkey information here which is really nice and those labels actually wrap around which is quite cool and then down below we have our button and of course our activity indicator that is going to go ahead and do it and there we go just like that we have our first application using mvvm and data binding all right so far we've created our first don maui application we've gone off into the internet and we've pulled down monkey data and we've displayed that information inside of a collection view all with mvvm and data binding now the next part up is a thing that every single application needs to do which is do navigation from multiple pages page a to page b and then to page c and back and forth now you want your applications to not be able to navigate but also present those in different ways with or without animations and modally or not and that is where don and maui's navigation services come in it enables you to do simple navigation to different pages or pass information including simple data types and complex data objects as well now specifically there are two different types of navigation services with don maui there's a traditional one that's based on navigation pages we're totally going to talk about that today that enables you to push and pop pages onto a stack but there's also one built into shell which is a uri based navigation system which is very similar to how the internet works or asp.net core works for example there are urls or routes if you will that represent this route goes to this page and you can go ahead and say go to this page or this page then this page it'll automatically push things on and off the stack for you enables you to easily navigate forward and back and go to different pages so let's take a look at shell and then also talk a little bit about that older traditional navigation style now i love shell because there's a bunch of different ways of doing our application including fly out or tabs on both top and bottom and even if you have a single page like we do in this application we're still going to use shell because it's going to give our application that way of doing all the navigation and unified styling i've talked a little bit about shell that has flyout items but it also has tabs as well so here are different tabs that we can see on the bottom and they're very similar and very easy to modify our application one way or the other there's also tabs that you can do on the top we like to call this tab sandwiches if you will because you have tabs on top tabs on bottom and what's great about this is that it's very very easy and it also delay loads those pages until they're navigated too now shall like i said has specific navigation service built in so for example let's say we start on our city list page or even our monkey page and we want to go to our detail page this is very very common in every application well what we would do is say shell.current go to async and go to detail now that detail is a string that we define and that we register as the route for this page and we're going to see how to do that in the workshop now what's great though is that it's very easy to navigate backwards to from that detail page over to our list page we can use dot dot this is really cool dot dot enables us to go up one layer i could do dot dot forward slash dot dot to go up two pages if i wanted to very similar to using the command line interface when navigating around the file system now like i also said though you may want to pass some different data to a page so for example you might want to pass the identifier of that city that the user tapped on here very similar to how urls work on the internet you can use query parameters and pass information these are usually strings but they could be things like integers that you pass around from page to page so here this is going to navigate to the detail page and then pass information either to the page or to the view model which is really cool it knows how to automatically cascade those across now how we do that is we set a query property so for example here we're going to say the query property is id which is what we saw in the url but it is going to map to a property in our view model or on our page called city id here this will automatically set the city id property for us when the page is created right after the on appearing is called you can also pass full objects to the pages too for example if you had a city object like cleveland where i'm from you can pass that in a dictionary here what i'm going to do is i'm going to pass it with a another query property identifier of city i'm going to pass that city across you kind of have a bucket of objects that you can pass across and again what this is going to look like is exactly the same here i have a query property and i have a city which is going to be our route that we've identified and also the property to set automatically and that is how we pass complex data objects around with danae maui with shell now inside of don and maui i talked about and said a second ago that there's this on a pairing property that happens every page has a bunch of different life cycle events so there is a traditional on appearing on disappearing that happens this can happen when you know your application goes to the background or to the foreground so they're important life cycle events there's also navigation events too so you can see when you are navigated to when it's being navigated from or when it's been navigated from fully so you can link into these specific events if you need to do some things in the code behind now you can also use something like the dynamic community toolkit and do something called event to command which would enable you to do data binding i have a whole video i'll definitely link here as well all about commands or events to commands which are very cool but just know just like window the pages themselves have a lot of awareness of what's happening with the operating system now let's talk about non-shelling navigation now this may happen if you're way down the stack or you're actually moving from an existing xamarin forms application or for some reason you really don't like shell there is the concept of having a navigation page and every navigation page has pages inside of it and its own hierarchical ui stack now when you use a navigation page every page has a service called eye navigation so i navigation has ways of pushing and popping pages you can push a page and give it a brand new page you would create that page in the combines as a new detail page and pass the data that way directly through the constructor i can also do things like pop pages too i can also push modals and pop modals and it's just a different method that you would call a navigation comparatively if you were doing this in shell you would just set the property on the page for the presentation style if you wanted to be modal or not so instead of having to call a different method shell has one method that you called which is go to async so what this looks like with push and pop async is that you push pages across from page one to page two and of course you can pop async which means you would go back unlike shell where you would use dot dot there's also advanced navigation so you can actually edit the stack if you wanted to you can remove pages insert pages you actually have access to the full navigation stack you can disable animations too if you want to so for example let's say i wanted to push this page across i wanted to go to page three and then page four what i would be able to do is remove a page by calling remove page and then passing it the page so when my users go back they go back to page two you would accomplish the same exact thing inside of shell by using that dot dot forward slash dot not to navigate back up the stack there the shell version to me is much more elegant because i don't need to keep a static instance around or somehow figure out what page is in the middle but that's up to you like i said there's also a way of inserting pages too so if you wanted to here inside this application you could insert a page before which enables you to get access and say hey input insert page 3a before page 3 and then it would go ahead and insert it there so now our navigation goes a little bit different again we could go ahead and handle this by using shell dot dot forward slash page 3a be much more elegant solution but know that you can totally do this with standard traditional navigation so let's go ahead and do some navigation you all ready what we're going to do now is we're going to go back into our service code into the next module and we're going to see how we can tap on a monkey and go to the next page all right you've come a long way i won't feel bad if you take a break right now pause the video come back in a little bit i did i took a little bit of break got some coffee got reinvigorated and i'm really excited because this next section is what a lot of applications are gonna need which is navigation and i'm in love with the shell and maui i know you will be too have whole videos here on youtube as well as amazing documentation and i love it because it is that uri based navigation and you can even do modal presentations really easily by simply adding an attribute on your page we'll take a look at that as well and also you can do this like back navigation with dot dot which i'll talk about and pass parameters back that way it's super duper cool anyways let's get into it let's do it so so far we have our monkey application i have it running here on both android and on windows and we can see we have all of our monkeys coming in here which is super cool look at our monkeys amazing so now what we want to do is be able to tap on these individual monkeys right we want to tap on them so let's go ahead and do that i'm just going to minimize this here i'm going to bring up visual studio and the first thing that we're going to do is we're going to go into our monkeys view model all right and what we want to do is we want to create another command and there's many ways of doing this but the one way of doing would be adding a command that essentially a tap event could register for onto the individual monkey you could also just have an event in your code behind if you wanted to in the main page here you know a lot of people ask me all the time james well what if i put some code in here like even this binding is that bad no it's fine i mean it says you're connecting your ui together it's not really anything test you need to be testing that's more functional testing as you use your app i'm okay with a little bit of code in my code behind but that's me every single person is different i totally understand it but that's me whatever you got to get a job done you got to do it but i'm going to show you how to do a command over here and it's a little bit more complex binding system we're going to take a look at it so here we have this you know get monkeys async command so we're going to do another async task of go to details async all right and then what we're going to do is we're going to plop an i command on top of this because this is going to be an i command there we go and this will give us go to details async and the the one thing that we're going to do here is we're also going to pass in a monkey as a parameter so let's do that and that's going to change the sort of life cycle of this command which means that it can take in null by default which is what this is doing there actually is a parameter that's passed in i command you know needs it for the execute but it's normally null if you don't give it a parameter but since we're giving a monkey we're going to pass in the monkey that we tap on so we can do first we say if you know monkey is null i guess here you would also say is null uh and if it is null let's hit return i always forget to use the is null it's way better than equals equals null so very cool and then uh if it if it is not null then let's go ahead and do some navigation so here's what we're going to do is we're going to say await and we're going to say shell dot current and we're going to say go to async now this is the main api here and we're going to give it a route and we need to register that route and we're going to make that connection now you can pass in any route here so this would be my route if i wanted it to be monkey details for example that's the uri that's the main uri that i'm going to be passing in here um so but what i'm going to do is i'm going to give this little dollar sign and do some string interpolation of name of and we're going to use the details page all right now if i just do that it's going to navigate to the details page and not do anything else and that's it and i like to use this name of because i said earlier you know i like to do this kind of page navigation i'm navigating to this page some people like to do view model first navigation so you could you could do name of your view model and then register and connect your view model on your page together it's a string it's whatever you want it to be right now the other thing though is that you can pass it those parameters so for example i had an you know id of you know monkey dot name for example i could pass that id over so i could say id equals and pass that across and that's a pretty good practice if you already have a database in place or a caching layer you don't want to pass full objects around or you have a lot of things really huge stack or you might not even have that monkey right like what if you launched this uri from the internet right through deep linking you're not going to have that monkey so you probably want to also accept some sort of id query that's in there now a lot of people love passing parameters so we're going to show that off so we're going to go to this details page i'm going to animate it and then we can also pass it in a new dictionary of string object and that's basically a key value store that we're going to pass along as we navigate so we can give it a key of monkey just like that and then we can give it the monkey all right there we go so this is going to be our query identifier here just like i have that id property here and you can combine both of those together but i'm going to put monkey and then pass the monkey across and that's it that's pretty much how you do shell navigation now again a lot of people like james oh my goodness what are you doing you are referencing your shell here well you could also you know create an interface here and then register your shell you can do the whole thing totally fine right it's whatever it's your applications whatever you want to do um totally totally acceptable here i mean if you're unit testing this method what are you unit testing really that you called this method so that's you know that's up to you it's up to you i'm not gonna i'm not gonna get deep into it but it's up to you do whatever you want i'm all about it okay so now we need to do is we need to call this method right so we know that our route name is going to be this details page we're going to need to pass in a monkey here and we're going to do that inside of our main page so my main page over here there's a few ways of doing that now i put selection mode as none because i don't like the background selection then i have to deselect that to do this other stuff but for example you could come in and you could say uh selection changed command and then command parameter and you could you know you could bind immediately to that um to that uh get uh was it get oh sorry go to details command here and the same thing you could do selection change parameter and then you would need to figure out what monkey you were passing in though and that's a little bit tricky like you know you'd have to figure out the selected item of this thing so that is uh conundrum i wouldn't really do it that way but it's possible uh per se you you could also do like a selected item and then you could bind that to a monkey and and do some different things there's a few different ways of doing it but what i like to do is say what is my user going to tap the reason i like to do this because what if i want to add swipe to delete in here that might pick up a selection mode on the cell when i'm swiping but if i'm really intentional with like i have to tap on something or click on something then that is what is going to enable just that tap event to occur so we're going to make it so that um so that frame this frame right here this monkey frame needs to be tapped on and then we can navigate to it and we can do that via gesture recognizers so i'm going to do is up here is i'm going to say frame dot gesture recognizers and this is really cool there are a bunch of gesture recognizers look there's typed in gesture let me zoom in here there's child gesture recognizer click gesture recognizer drag drop pan pinch swipe tap i'm going to use tab i guess you could use click as well i'm going to use tab that's a new one but tap is is cool because it also lets you set the number of taps required so if you wanted to be like you need to tap on this 10 times to go to the monkey you need to do that okay so we need to tap and we want to you know we could set the tapped event and we could set that in the cobine but the nice thing about these gesture recognizer that there are commands and command parameters so the command parameter is easy that is just a binding to dot because bind to myself i am the monkey right so i'm binding to myself now the more complex one is actually the command itself and you're probably thinking like well just obviously james bind to the uh go to details command easy that's probably what you're thinking right no that's not that's not exactly how it is because this monkey doesn't have the go to details the monkeys of view model does so what we're going to use is a special type of syntax here we're going to set the source now the source itself is is telling it what to bind to so here the source is this monkey because if i had name in here then the source would be still the monkey and the dot is the core source so we're going to change the source and we're going to use something that is called a relative source and specifically here there are a few different things there's a mode an ancestor type and an ancestor level and this relative source basically looks up the binding context to say hey go find something of a specific type so we're going to say well the type that we're looking for i'm going to keep scrolling over it's quite long so bear with me is an x type of view model monkey view model of monkey view model i'm not sure why the intellisense isn't coming up there but it should be there all right so we have that and then now what we're going to do is we're going to say path so on that source what is the path well that path is the go to details command okay so let's walk through it again so the source don't use the dot don't use the monkey but look up the binding chain okay for something that is a monkey's view model so go find that and then what you're going to do is look for a specific command or property that is called go to details command this is really really nice it's advanced but we're learning here of how we can go ahead and do this which is really really cool and then of course we're gonna close it off that's a long one that's a long tap gesture recognizer there but it's there so again we're walking up the stack finding it there and you know i have to do this quite often whenever you're dealing with these lists you might have a swipe view for example where you're swiping to delete and that delete command is on the view model so you need to go up that stack right okay cool okay so the next thing we need to do is we need to pass this monkey over to our specific page all right now there's a few ways of doing this you could go on to the details page over here right and you could come in and then do a you know you could put the you know something called a query property on the page and that query property would be that identifier so here it takes in a name and an id so it'd be the name is the name of the property to bind to and then monkey would be the there so that would be what it would be and i'd have to create a public monkey monkey for example and then now when i navigate across it's going to know to automatically bind up that monkey based on this name and this specific query identifier and then that's this monkey here so they all align right they're all strings knows how to resolve them now we're not going to put it on the actual page though because donna maui is smart enough to know that if your details page or the page you're navigating to has a binding context set it may also want to take query parameters so it'll automatically cascade so let's go ahead and put in the the monkey details view model here i'm just going to say view view model and then say binding context context equal to the view model perfect now what we're going to do is go into the monkeys details view model and we're going to go ahead and add that query property there and then what we can do is we can come in and say let's give this a public monkeys uh monkey details view model this little constructor and then i'm gonna go ahead and put in a a monkey of monkey and give that an observable property perfect so now when i say this dot monkey i have my monkey because the community toolkit has automatically generated that backing field of the public getter and setter based on that all right so now we have this is we're all set we have our monkey over here it's doing cool stuff and the final thing we need to do is register the route like we set the uri that we wanted to go to of this details page but we didn't register it with the system now if i go into the app shell and i look at this content page we can see that this main page is registered the route is main page right so if you're adding tabs and you're doing a bunch of other things all of your shell pieces of content your tabs would have a route and they could have deep deep deep routes too so this could be slash you know whatever t or i don't know whatever it would be so you can you can kind of cascade those down downwards tab and then the page inside the tab and you would navigate around so we need to register this and what we're going to do is go into the code behind of the app shell so if i go and minimize this down you can zoom in and see this app shell xaml cs i just dropped it down and we're going to go in and say routing underneath the initialize component dot register route and this is going to need two things it's going to be a string which is going to be the route itself so i'm going to say name of details page and then i'm going to say the route factory which it happens to be an option or you can just pass it the type i'm not really sure what a route factory is but i just always pass it the type so it basically says hey go ahead and inflate and create the details page when you navigate to details page for example here so that's pretty cool and again that name of so if we go ahead and look at this this equals details page so if you don't want to reference that details page itself you can just put in the string that's totally up to you all right now the final thing we need to do because we are using this dependency injection all the way through our pages is we're going to need to register it over here so i'm just going to go ahead and now add a builder dot services but this time we're going to add a transient because we're going to want to create a new view model every single time with a new monkey i'm going to say monkey details view model and the same thing here we're going to say builder dot services dot add transient we're going to do details page right because we're going to create a new details page every single time we do this that makes a lot of sense right so we register everything here we register our routes inside of our app shell we have our details page which is injecting in the details view model and now our details view model over here is pretty minimal all it's doing is taking and just assigning a monkey to a monkey and setting it up there and that's it basically for all intents and where this gets initialized if i was to do override on navigating to or navigated to this is where we're going to see the monkey be set it's going to create the it's going to create the page right it's not going to be visible yet but it is going to then create the view model pass in any dependencies and then it's going to assign the query parameter so everything has to be inflated and then in between the creation and the on appearing and navigated to it's going to set those things so it's going to show up immediately on your page and you'll be totally good to go but yeah let's go ahead now and just run this and now we should be able to tap specifically on one of those monkeys and we should be able to navigate to this new blank page of our application so that should be pretty cool uh in general and again very very minimal amount of changes were needed here so if we review it over here again we have the the transients being all registered up and you can of course create extension methods or something like that there and then our details page taking in the view model um let's add that breakpoint there just so we can kind of see it come in in real time and again we don't need to really do much into our main page because we don't really adjust anything all right so let's let this compile up here and then deploy over to our android emulator all right here's our application so i'm going to go ahead and hit get monkeys and sure enough okay well we're going to stop those break points that we put in earlier and there's our monkeys now i'm going to go ahead and add a break point here in our monkeys view model so we can actually see this event happen so i'm going to tap on that monkey now we see this monkey is coming in with all the different monkey information which is pretty cool and then we're going to navigate across and notice that we're navigating here and at this point our view model our binding context has the monkey set automatically okay so it's already navigated too but it's already there so it's being navigated to we have our binding context here and if i continue on and we're just going to wait here our data contacts our binding context of that monkey has been set so what this means is if we go in to our details page let me open that up just like this we could start doing some data binding right so i could come in i could say label and i could say text and do a binding here to monkey dot name put that in there and hit save and we see baboon right i could say font size maybe 25 make it bigger and you can see it there right i could i could now come in and i could say title and i could say the same thing binding monkey dot name hit save there like i said baboon pops up right on top of there because that it's been passed and the binding has been set automatically and we're totally good to go now we want to get rid of these little dot dot dots here so we're going to go ahead and use our x data type so we're going to set a name space of view model just like we had before type in view model and then what we're going to do is we're going to come in and say x colon data type of view model and this is our monkey details view model this time and now our little dot dots go away and we're totally good to go and we should get nice intellisense here there we go which is cool so there's our name if i wanted to do dot details put that in there and now we get our details coming in from our label which is pretty cool all right so now what we want to do is we want to turn this specifically into something like this okay so we have like baboon details and we have other things here going on so we want to kind of put this like nice little type of application together and look dissimilar ask of that so here's what we're going to do is we're going to now build out our content page so the first thing we're going to do is we're going to put everything inside of a scroll view and we want to do that because maybe that details like really really big wouldn't be able to scroll up and down before we had a collection view so that was handling the scroll for us then we're going to stack a bunch of stuff on top of it we're going to have this like nice grid on top and then what we're going to do below is put in some detailed information about the monkey so i'm going to put in a vertical stack layout here and then what we're going to do is we're going to put in a grid and just kind of bear with me here we're going to put in a grid here and the first is going to have some columns it's gonna have three columns here um auto and then star so kind of i'm gonna put something in the middle and then space it in the middle uh and then we're gonna do some row definitions oops i don't need a thing there row definitions and the first one will be 160 and the second one will just be auto perfect so we have our grid set up inside of our vertical stack layout and now what i'm going to do is i'm going to set a background here if you if you saw this image up top what i want to do is i want to kind of create this uh this yellow background and then i want to kind of shift the baboon down a little bit so like it kind of is overlapping so it's half of this color and half this other one and there's a lot of ways of doing this but this is at least how i did it for the workshop so we'll see if it really aligns with with what makes sense in the real world but at least for me i you know not the like end-all be-all best um you know ui designer in the world but i think i'm all right so let's do background color and we're going to assign that to a static resource of primary here so actually if we scroll up we can see i have a a few i have accent uh light background dark background i'm gonna do primary then i'm gonna do grid dot column span it's gonna be all three of them i'm gonna set the height to 160 because that's going to be the the row the first row i'm going to say horizontal options fill and expand so ideally what we get and i save that is well we don't get a data binding to our primary there because i guess the static resource and the hot reload didn't connect up all right that's fine um but if i i guess if i set this to orange i guess we would see it let's go ahead and do that there we go now we get our orange there we'll fix that up though i'm gonna put that back and see what that does it leaves it at least but we'll we'll put it back for now all right and again that might be already fixed up by a time you see this i'm kind of recording this video pre-ga so let's see you know there's always tweaks and optimizations there okay so we want to now put that image inside of that [Music] sort of box but halfway down and we want it to be a circle but if you remember our monkeys were squares so how are we going to do that well what i like to do is i like to put things inside of a frame and then i like to give things corner radiuses and then that makes it a circle so check this out so this is kind of cool i'm going to say frame and i'm going to give this a grid dot row span so it's going to span multiple rows i'm going to say grid.column put that in the middle and then what i'm going to do is i'm going to give this a height request of 160 a width request of 160. so it's perfect and then i'm going to say corner radius is 80. there we go and we're going to say horizontal option center and padding is zero and then what i'm gonna do is i'm gonna say margin i'm gonna shift it down 80 from the top so that way it sits right in the middle right so if it's 160 160 shift it down 80. boom you're right in the middle perfect all right now the other thing i need to do is i also need to tell it to clip and essentially on some platforms you need to say is clip to bounds and that'll make sure that it clips anything that goes outside these bounds which is going to be the image so we're going to set that there and now what we need to do is actually put the image inside of here so let's put the image in here aspect is going to be aspect fill height request 160 uh with request 160 and then i'm going to say horizontally center it vertically center it's right in the middle and then let's set the source to a binding of monkey dot image there we go close it off hit save and we have our monkey in the middle oh my goodness uh which is amazing so there's our monkey it's a perfect circle and perfectly 80 away from it right which is pretty cool so i love it so that so that's it so this is this first one here this first uh column uh and row so it's going to span three columns it's going to span one row and then i set this auto because i don't want the content underneath it to overlap so i'm kind of incorporating that into it here so that's pretty cool so this is grid box view a frame an image here and we're good to go now underneath this what we're going to do is we're going to put in another vertical stack layout we're going to give this a little bit of padding though of 10 and a little spacing of 10 as well there we go what we're going to do is we're going to put in some labels and we're going to say text and we're gonna say a binding to monkey monkey dot details there we go let's do that and then we're also gonna do location and we're also gonna do pop mulation all right so now we get that in there now something else that you can do too is that like this is fine that's just a number but you can also do like something called a string format which is nice too we saw this earlier but you can come in and say string format and i'm going to move this down over here just so we can kind of see it let's say string format and i'm going to say population [Music] and then here this takes in standard string formatting there we go of just that i'm going to hit save and now we see it says population 10 000. i do the same thing here so if i wanted to i could come in copy this then do location just like that and now we see it's doing the string format so that's really really cool you can do string formatting if it was numbers and ins you could put different decimals or two string things like that it all works now we're also going to do they're going to come in and we are going to add some styles here so i'm going to say style i'm going to say static resource to our i don't know maybe our medium label that we have that'd be pretty cool and then let's do the same here we're going to drop this down and we're going to drop this down and we're going to say style and i don't know static resource it could be of a let's do a small label you can do micro label you kind of pick and choose from the different ones that are in here i'm going to hit save but again it's not going to pick it up so we'll do a reload here to get that going and let's while we're at it do a static resource of our primary again all right so kind of getting around that but now we should be able to hit this little uh restart button and what we're going to see here is that as we click around and navigate it's going to pass a new monkey create a new page and we should be totally good to go and that's going to start debugging again that little refresh icon there too so we get our monkeys we get our spinner get our baboon all right we got our monkey go across boom we get our baboon we get this information here we go back click on blue monkey get our blue monkey go our squirrel and we have our different sizes and our different shapes here and of course you can adjust those sizes and shapes as long as you want them so boom amazing so cool look at that now a lot of people ask me hey james hey james what if i want to manually do like a modal well that's actually really easy what you can do is you can come up onto your page and you can say shell dot presentation mode and then you can say animated moded animated or not so when i do that i need to refresh the application but when i do that that will put it into a modal presentation state so let's refresh that and see so you're sort of assigning and say this page is presented modally which is quite nice and you can do that in code too so if you're going to do it however you want you can do that there so let's reload our monkeys and then let's tap on one and see how it floated up from the bottom boom right now here i have a back button so i can actually do that and i can i can say that's going to go back down but you know in general you might want to add a back button because on ios there is no back button right so you need to handle that so you need to go backwards so i'm not going to go ahead and do the modal animated we're going to just remove that but let me show you what it would be like to actually navigate backwards so what i would do is inside of my monkey details view model is i would create another async task of go back async here and i would make that an i command and then what i would do is i would await on shell dot current dot and then what i would do is i would say go to async and i would do dot dot dot dot dot is essentially go back it's very similar if you're navigating around the file system in the command line you do cd dot dot you could also do dot dot slash dot dot and that would go back two pages you could do dot dot and then i could say details page i could do go back and then go to a details page you could go back and then you could also pass in parameters you could say id equals one and that would pass back parameters to the first page so if you were for example doing like a sign up form or an okay submit cancel or wanted to pass off back you pass that back over there that's really cool and that's how you would navigate backwards and that's how you would do modals other thing i get questions about too is are these different monkeys being passed as reference types and i'm pretty sure yes they are being passed as reference types it's not doing serialization or anything like that it's just hey i have this object i'm creating that page assign it when it goes through i'm 99 sure and if for some reason i'm not sure i will put a thing right here or down there that clarifies that but yeah you're just passing objects around in this bucket and you'll totally be good to go which is rad all right we did it we totally navigated let's let's do it one more time just for funsies so here's our monkey application rad uh over here we're gonna say get monkeys tap on a capuchin boom we're totally good to go now let's also come over here and let's deploy it over to windows just for good measure to see that in action so we have our monkeys now this is using our previous data i didn't redeploy it on android so now we have that modal still so this new one now that i'm redeploying it here on windows shouldn't so we can see that here so let's go ahead and get the windows app loading i'm on a wide screen let's push it down here perfect hit get monkeys we get our little spinner oh we got our monkeys and boom we're navigating across just like that which is awesome we did it we got our monkeys we're navigating across totally good to go and boom done some navigation and that's one of the key things that you're going to be doing inside of your application over and over again all right navigation check done but our next step is to integrate some sweet sweet platform integrations into this thing which i am so excited about uh because that's what really sets done maui apart and makes it really special is being able to access a bunch of native features and cross-platform so let's head over and let's learn about accessing those native features with dona maui all right so far we've now seen how to build our application display data and navigate from page a to page b and so much more but the next thing that we probably want to do is start to access some native apis to really make our application set itself apart from the competition what's great about don and maui and the underlying ios and android 4.net systems is that they enable you to access those platform apis from c-sharp and specifically done at maui has a bunch of cross-platform features built right in so let's go ahead and talk about that and then get into the workshop so let's talk about accessing those platform features and why they're so important well if we take a look at a normal structure of our application with apple platforms android and windows we have that shared c sharp back end we've had that user interface and that view model and our model and our services but there's other stuff that can be accessed up here which is also important which is those platform specific apis those are things such as battery gps lights notifications or even some of the platform user interface code that you know we just haven't exposed yet inside of don and maui or maybe there's not a library out there or maybe you're a library creator you want to access some really cool new user interface feature in ios 15 for example well those are all available in c-sharp that you have access to and done in maui so let's say we wanted to create an api called speak and we wanted to use text to speech well on all the different platforms there are ways of doing this so if we wanted to we could implement the code and create an interface for calling speak on the different platforms so we might do something like this which is create a public interface called i text-to-speech create a speak method that we would call and then implement it on each platform so in ios we'd use av speech synthesizer write a bunch of c-sharp code on android we'd use the text-to-speech api write a bunch of code and on windows we would use the speech synthesizer and again write a bunch of code and then at the end of the day we would use the built-in dependency services to register that text to speech right here so we could register the ios android to windows service call into the dependency service of donna maui get it back and then call speak we could also use built-in dependency injection in ioc like we did for our view models and by adding a single tin of itex to speech and passing it the text-to-speech implementation and that's really great because we can then inject it directly into our constructor and call that speech back but when we're thinking about this it seems like there's probably a whole bunch of different common apis that are available such as you know microphones and cameras and preferences and geolocation and wouldn't it be nice if there was a single common api for all of them for these common different things on the platform well there are things like geo location device info display information preferences secure storage connectivity are all available inside of donna maui with cross-platform apis just like we have built our user interface with our user interface cross-platform api there's a cross-platform api to access these native platform features which is oh so cool so for example if we wanted to get access to the geolocation of the device we could just use the geolocation class that's built into don and maui similar ones for connectivity and preferences and text of speech already exist over here here we can get the last known location or specifically call and get the current location and gif at different settings we can also use built-in dependency services because every single one of the apis has an interface and a default implementation so we can register that and then also inject that into our constructors too the team has really thought this out and it's really beautiful to see this all come together so what we're going to do now inside of our monkey application is use this geolocation service and we're also going to use the map service actually launch maps on windows and android and ios and mac to actually display our monkeys on a page so let's hop back over to the workshop and do that now all right let's get into it we're going to do three things specifically inside of this application the first thing we're going to do is add the ability to check for internet connectivity using the built-in connectivity apis of don and maui then we're also going to try to find the closest monkey to us via geolocation and we're even going to add a button on the details page to open up the maps application on the different devices so let's go ahead and start our implementation all right so so far we've added our monkeys we can navigate around as we can see here which is pretty cool and we're kind of like ready to start doing more advanced things in the application now if you remember we added this get monkeys button that goes off and checks things on the internet and that while that's good we probably also want to make sure that they have internet connectivity so what we're able to do is go into our monkeys view model right here and we would probably want to check something right about not here this is go to details right about here right right before we say is busy and we go and get the monkeys we probably want to check to see if there is internet now you put it there you could also put it into the get monkeys here as well so if we wanted to we could check for internet right before we get it it's kind of up to you where you want to put it but i like to put it in the view model totally up to you so what we're now going to do is we're going to use the built-in connectivity service built into don and maui so we're going to create a backing field called eye connectivity and this is going to live inside a microsoft maui networking now there's about six or seven or eighty or a bajillion different apis a link to the documentation for them but they're built in and what these do is add that abstraction on top of the native apis that are built in to the native platforms or ios android mac and windows so while icon activity will give us a specific api know that it is calling the underlying api so check this out visual studio way too good it's going to inject this into our view model right so this is why i really like that dependency injection service why i enjoy using shell and all that goodness inside of here is because it enables us to keep adding on for what this view model needs so now all we need to do is go down here and i'm going to say if connectivity dot and here i have access to connection profiles connectivity changed events and the network access i'm going to say if it does not equal network access dot and we have things such as none unknown internet constrained internet we're going to see if it doesn't have internet well then we'll return out of here but let's also pop up a display alert so i'm just going to copy it from down here shove it in here and of course instead of unable to get monkeys we're going to say check your internet and try again then it'll say internet internet issue probably maybe not as many as exclamation points and needed you need to yell at your at your uh users of your output were there so check that literally one line of code to grab that there cool now we're going to do is also come into our maui program and the only thing we need to do is come in and register these services so we're going to use three different services we're going to use a connectivity geolocation and map and those are all icon activity igo location and imap so we might as well just register them all now so we'll say builder dot services and i'm going to add this as a single 10 as well i'm going to say i connectivity and what you're able to do in the constructor is pass it a default implementation to use so here i'm going to say connectivity dot current all right so how don maui is set up is that there's a default built in publicly you know not static but you know singleton basically inside of it so we're just registering that with our service here i'm also going to say i geolocation and this will be geo location dot default some of them are not current some of them are not default i'm not sure why the team picked those but up to them and then i'm also going to do imap here i'm going to say map.default as well perfect cool so we have registered connectivity geolocation and a map now i'm going to run the application in non-debug the debugger actually requires you know on the emulator itself to to have internet capabilities enabled so if you take it sometimes in airplane mode it might disconnect so i can be a little bit odd but let's go ahead and do this i'm just going to go and shove this into airplane mode so now we don't have internet i'm going to click get monkeys and boom just like that internet issue check your connectivity and try again well now if i take this out of airplane mode boop now our emulator has uh internet again wait for that to come back up boop and just like that we have internet and we're able to get our monkeys which is so cool look at that like literally a line of code just registering it up it's totally amazing so good it's so unbelievably good i just love it all right now you're probably also wondering well there's a big blank section here and that's because we want to actually use the geolocation service to find the devices geolocation and find monkeys that are close by and pop up a little dialogue so let's do that so let's go ahead and i'm gonna go and close this out and we're gonna open up i'm just gonna close all these tabs and i'm gonna go ahead and open up the monkeys view model and the first thing we're gonna do is just like we had icon activity i'm going to say i geolocation geolocation and let's see a visual studio will do this as well oh my gosh so good so we pass in igo location get our geo location and we're totally good to go now we're going to do is we're going to add another i command and this is going to be an async task of get closest monkey now you can mark it as async or not async it doesn't really matter because the i command that we add here for source generators will automatically add or remove that so we can make this async if we want everything to be a spacing here for naming purposes totally up to you okay so inside of this the first thing we would say is like if is busy or our monkeys dot count equals zero then let's return because i don't have any monkeys there's no closest monkey or i'm getting monkeys right now on the internet so don't go ahead and you know get that stuff and then what i'm going to do is i'm going to do a try catch over here and we're just going to catch all exceptions this could be a permission issue this could be a series of things that go wrong here but what i'll do here is i'm going to i'm going to grab this other error that we had that we have so let's output this here just like we did before so i'm going to get unable to get closest monkey and just put out that error and that's important like we want to whenever we're calling these native apis things could be turned off on the device geolocation could be turn off for example internet issues whole bunch of things you always want to make sure you put those in try catch and read the documentation to make sure you know what's going on there all right so the first thing we're going to do is we're actually going to use the cached location this is kind of one of my best practices based on what you need location for if you type in geolocation dot we can see that we have get location async and also get last known location async and that's really nice because that enables us to grab the cache location first we could check time codes and how old that is else actually pull the real location i'm going to say var location equals a weight geolocation.get last known location async i'm going to say if location equals null and here's where maybe you would do that time check if it's null or it's older than a month maybe you're older than a day older than an hour let's go ahead and get the real location so location equals again a weight geolocation dot get location async now i can just call that method i'll use the defaults but it can also take in a new geolocation request that's what i like to pass in because it enables me to do two things we can set an accuracy which is like how accurate do you need it to be um you have like low high highest best medium is pretty good and that sort of will tell the operating system based on the different one and maybe use wi-fi versus real geolocation versus cellular things like that i'm also giving a timeout and we'll give it 30 seconds because visual studio recommended it so why not and timeout's nice because if you don't really need it immediately or you for some reason you know want to give up after 30 seconds and then just use the cache location then you know you could you can give it a timeout and that'll throw an exception awesome so now let's say we have our location so again i'll do if location equals null for some reason let's return out of there just in case because we don't have it we should probably do a pop-up but that's fine but what we'll do now is we'll say var and let's grab the first monkey in the list but we're going to order them by how close they are to us so right so let's go through the monkey list and say hey monkey how far away are you from me from my location how far away are you from you and then order those um [Music] in the list ascending which would be pretty much the closest would be like zero for example to write on tommy so we'll say first i'm gonna say monkeys dot i'm gonna scroll up to the top here we're gonna use link so we're gonna use order by and i'm going to tell it that for each monkey okay let's do m dot and then we'll do location so from me there's an extension method where i can open the maps async but i can also calculate distance this is really cool and this will take in a end location and units or it can take in a latitude longitude for example which is cool um so let's go ahead and do m dot latitude m.longitude and then the units which uh don't really matter distance distance units.miles because it's just a number that we care about there um all right and then we'll do dot first or default cool and then again if for some reason if first equals null which it couldn't but if it did we'll just return and again is null i'm so used to my old ways but is null it's definitely the better way of checking against nulls there so we're we're passing in our latitude and longitude right into this um into this so we're calculating how far away the monkey is from me finding that first one the closest one and then we're going to pop up an alert so we'll say await shell.current.displayalert we'll say closest monkey and i'm going to say um let's do a string we'll say uh first dot name uh in first dot location oh no yeah location there we go and then we'll just say okay there we go awesome so not too bad we go and we just make the geolocation request with just a few lines of code and again we'll do is null we've got to get that right one of these days and we'll be good to go okay so now we need to do is call this get closest monkey command that's been generated for us we're gonna go back into our main page scroll to the bottom or just collapse that and put in a another button so let's get that button there we're going to say find closest there we go and this one is going to be called get closest monkey command there we go and the difference here is that this will be in row one but it'll also be in column one all right so now at this point what we're going to do is debug the application and what we've done and what i've configured ahead of time for us to actually open up the solution is that on each platform i have automatically configured the required settings that are needed so here's the permissions needed for geolocation for example if i was to open up the ios info p list let me do open with let's just do xml editor we can scroll in here and we can see that this is the location when in use that is needed so i've given each of the different platforms the ability to request the location so let's go ahead and just say get monkeys i'm going to say find closest and we'll say yeah while using the app this is going to go now grab our geo location and we see oh the closest monkey is henry in phoenix in fact let's add some breakpoints here so and we can see here if i tap on this that the location is going to be set to mountain view because that's where the emulator default is which is cool but let's go ahead and open up our monkey's view model let's add a break point here and a break point here and a break point down here say find closest we have our monkeys 13 monkeys we'll continue on our cash location right over here we get that direct information we get the time stamp for it we get the accuracy a bunch of information course altitude altitude reference system all this good stuff there's a lot of stuff in there if it's coming from a mock provider which is not true in this case if you were doing a mock location we can see that our location is still not null and then boom sure enough we find henry very cool and just like that we have geolocation built in to our app i mean this is literally just a few lines of code which is cool now this geolocation is handling the permissions for me but there is also a permissions api built in to don maui so here i can say request async or i could say check async and i could pass it permissions dot location when in use for example and this would go off check the permission make sure i have everything and i could be controlled in control of it so that might be one thing i want to do in this app is instead of letting the geolocation api of don and maui check for permissions i may want to do it myself so you have that ability inside of dotnet maui all right the last one here why not let's do one more let's go into our view model into our monkey details and let's pass in an imap right so we had a map earlier so we're going to pass this in you're probably wondering what this constructor is doing here well that's what it's there for now and let's do this let's go in and just simply say a new i command and let's do an async task of open map async why not we're just going to keep it with the async here and again we're going to do a try catch exception and because i'm uh you know a little lazy i'm just going to go ahead and copy and paste this code around there we go and here we'll say unable to open map now you might want to catch that exception because if you open the map application to a specific area on a device the device might not have a map application for some reason maybe it doesn't have google play services on it or maybe the user uninstalled the application or turned something off so you definitely want to do that now this is cool all we got to do is a weight and say map dot and i can do open async or try open async so try open async will sort of return a boolean instead of the exception so you could do that there so totally up to you now all we need to do is pass in a location or we could pass in a place mark or a latitude and longitude so let's do that i'm going to say monkey dot latitude monkey dot oops monkey always use the capital one there dot longitude and it's also going to take in a new map launch options and this is pretty cool what you're able to do is give it a name so display so let's just say the name is the monkey dot name then you also give it a navigation mode and this is really neat you can tell to launch the map app into driving into transit into bicycle or into none which is just hey open the map and display it cool all right so now we need to do is add a button to click this thing let's do it so let's go into our details page this time and i'm going to go ahead and under the grid but maybe before this vertical stack layout let's add another button in there i'm going to say text i'll say show on map let's do a command here there we go to a binding of open map command i'm going to say horizontal options let's center it let's give it a width of 200 for good measure let's give it a little spacing between stuff and then we'll also give it a style of the same one that we're using on the other page which is the button outline boom and this is going to go under the grid under the image but above all the monkey details that are there which is quite nice all right so let's go ahead and do this over here so we're going to launch this up and see this working uh over here so let's go ahead and get our monkeys say get monkeys i'm going to go ahead and click on the baboon and then we have show on map and boom we're launching uh google maps now i apparently don't have it signed in or registered or things like that but boom just like that our monkey is there and i would be able to zoom in and out wherever this monkey is at i guess let's go ahead and do another one let's do uh mooch in seattle open on map boop this will probably give us like some stuff so there's yeah now we're down in seattle and fairmont i used to live up over here somewhere amazon go all sorts of stuff so there you go we're opening the map to the specific location of where that monkey lives which is quite awesome all right now what i also want to do is i want to tell you a little bit about some platform specific tweaks that you can do because while so far we've used these really cool apis that are cross-platform they're also these things called platform specifics and don maui offers these up so a great example is on ios this safe zone that needs a safe area that needs to be used specifically when dealing with the notch for example so this is actually something that's really really cool so i'm going to open up the main page over here and i'm going to go ahead and add a new name space up here for ios specifically this is going to be a little crazy let's say ios i'm going to say ios specific okay now i want you to notice what happened here on this long title is that this brought in a namespace of don maui and then it said that is in a specific assembly and that's really cool so you can reference other assemblies inside of your application now what this gives us is extensions to say ios colon and i can say page dot use safe area true or false all right and that's going to enable me to go ahead and make sure that when i have a notch that it's going to space things correctly so how about we hop over to my mac really quick we're going to boot up the application for ios and we're going to see this with true and false and then we'll officially completed our next module which is all about using platform api so let's head over there now let's do it all right here we go we're inside of visual studio 2022 for mac and we can see here that we have the safe area set for ios and when i go ahead and bring up the application we can note that nothing is overlapped in the status bar or in this little area down here and click on get monkeys and sure enough there's all my monkeys i can do find closest and there's henry and phoenix that's using mock service data from the actual simulator and i can tap on a monkey and sure enough there i am now if i open up the mac application you can see we also have a mac application here and click get monkeys there's our monkeys and sure enough i can navigate as well which is really really cool now if we come in here we can see that this is visual studio 2022 for mac so we have all the normal things that we would expect so here's our views and our view models and all the things that i showed you before you can easily select what you want to deploy on if you want to deploy directly onto your mac you can select your mac you're good to go and that's all working because again if we open up here the main file we can note here that we are multi-targeting so automatically mac os picks up all of our deployment targets and android emulators as well and there you go now we've deployed our application directly over to mac and over to our ios simulator looking absolutely beautiful now we just implemented some native platform features using the built-in across platform apis and don maui now you may be thinking well what's next what else can we do well i like to think about after we've started to build our application we may need to think about the styling of our application based on the form factors or how our designers or if you're the designer want to display data to our users so far all we've done is displayed a list of data in a vertical stack pretty much inside that collection view we also tapped on an item and navigated in now you might be saying well that doesn't seem like very much like a collection of things it seems like a list of things well there is a list view built into don and maui but collection view is sort of the next evolution because it is much more flexible so what i want to do is break down a little bit about what the collection view is now that we started to use it and all of the other things you can do with it such as empty views and pull to refresh now what we've seen is that collection view is a way of presenting data with different layouts it aims to provide a flexible and performant alternative to the list view you can think of it as the next evolution of the list view but why would you want to use collection view instead of just using the list view because the listview has a lot of nice features it has a different swipe to swipe to delete actions in it it has click events obviously it has group headers too well collection view like i said has all of that and so much more and a much more flexible way of doing it that is much more performant so first and foremost the collection view has a flexible layout system it enables you to present things vertically horizontally in a list or in a grid now you can also create your own custom layouts to display data however you want it also supports single and multiple selections so if you need to do multiple selection you can have that built right in it has no concepts of cells it just uses a data type directly so it actually requires less xaml or less less code to create each item inside the list it automatically uses virtualization to provide optimizations by the native controls under the hood it reduces the api surface of the list view many of the properties and events are not present in the collection view because they're not needed but there's many new ones that are optimized for displaying lists of collection and specifically what we mean by they're not there they're available in other ways for example pull their refresh which i'll talk about here in a little bit it doesn't include built-in separators because that was annoying for many many developers you can add them yourself and additionally what's nice is that the collection view will automatically throw an exception if things have been updated off of the ui thread with the list view it was kind of hard to know one way or the other and could get yourself into trouble so this is nice when you're developing your applications there's many many things here but also put a link to documentation and of course a video that i did criticizing and optimizing and looking at both list view and collection mewtwo i have a lot of videos here on the youtube and heck if you're liking this video make sure you hit like and subscribe so you get notified whenever i put out a video all right so what i said is there's lists and there's grids so here we have a list you can do it horizontally you can use a grid you can say how many items are in each of them left and right up and down all the different things you can also specify headers and footers which are also nice so if you want things on that top or on the bottom you can do that too there's also an empty view built in so all you have to do is set the empty view and if there's no items it will go ahead and display that there's also groupings built in too which is a collection so you can have different groups of items very similar to list listview as well and that grouping is also important because you want to display different types of different information in different ways for example in the podcast application that i'll link to which is a beautiful donna maui application it links a two different section of what's new and specifically for you and that uses a collection view and it sets the is grouped property what's great about that is that it enables you to set a different data template for that specific grouped header you can interact with it and it's very very optimized as well so this is really nice if you want to have different groupings all right let's talk about pull to refresh now things are a little bit different between the list view and the collection view and i want to talk about that specifically here because often you're going to want to enable your users to pull down and refresh that data now i often come in and i have a view model and i have things such as an is busy and an is refreshing and i often have a method that's called like refresh such as refresh the data or get data and that's what i want to have called when the user clicks on a button to get data or when they pull to refresh so what we want to do here is use those different booleans to say if the data if i'm already doing something don't do it again but also control that refresh mechanism so when i pull the refresh is refreshing will automatically be set to true and it will call that refresh method and then we'll control so we make sure that we don't call this over and over again with is busy and what this would look like inside of a list view is a bunch of different properties so for example we would say is pull the refresh enabled we have to set that to true we'd have to do a data binding to the refresh command and then we'd have to do another data binding to the is refreshing and this is this complexity that's added into this list view as this feature was added there's a bunch of other different events and things that were triggered here so that's why the team decided to decouple refreshing from the list view and they created a refresh view this gives it a much more optimized scenario to handle anything that can scroll including list views scroll views and the collection view it can also be used by other controls that are out created by control vendors or by the community so if anything is scrolling it can go ahead and be put into a refresh view it's much easier here we have a command just like we had inside the list view that is doing data bindings to the refresh command and then an is refreshing that is automatically turning it on and off and this is nice because now we've separated the concerns of our refreshing and our collection view and it's very easy as we can see here it minimizes the api but it also gives flexibility with some new controls and colors for that control which is really great now let's go ahead and do it let's optimize our collection view with an empty view by modifying around some of the different ways of displaying data and implementing that pull to refresh all right you've made it to the next module all about the collection view and optimizing it with awesome different layouts and pulled a refresh and even an empty view it's really really cool there's a whole bunch of really cool flexibility built into this thing that i love now if you've made it this far i have to assume that you're enjoying yourself a little bit and if you are you'll be super awesome if you can hit that like button down there over on youtube i know i've said it about 20 times in this video but be super helpful that only not only tells me that you like this video on this type of content but also helps others right here on youtube find this video goes in that magical youtube algorithm of goodness the recommendation engine that no one knows how it works but except for if you hit that like button that's super good now if you want to go a step further you can also hit that subscribe button down there while you're there and what's cool about that is that in your subscription feed on youtube app and on the website you're going to see all the new videos i put out every single week if you really love what's happening over here ring that notification bell and that's going to actually send you little push alerts whenever i put on a new video i only do like one a week so it's not crazy so if you're into it go ahead and check it out but let's get into our collection view i super appreciate it if you hit that like button all right here's our monkey finder we got monkeys we're navigating we're doing geolocation we're doing all this stuff it's amazing but what yeah what if we wanted to add some more things like pull the refresh for example or put these things in a grid wouldn't that be pretty cool let's do it let's go ahead and close these down and take a look all right the first thing we're going to do is come over into our monkey application and we're going to spend a lot of time just directly in the main page and the monkeys view model now so far our collection view is just right here it has it's in two columns spanning and it has this collection over here that it's doing data binding to and then down over here we have a button and that's fine but it would be great if we could do a little pull to refresh so there is no you know refresh thing over here there's a bunch of different events like threshold remaining reach scroll to request a whole bunch of other stuff but what we really want to do is add pull to refresh and how we're able to achieve that is by using the refresh view so we're going to wrap the collection view in a refresh view so i'm just going to indent this put that in there and add a little break perfect now the collection view no longer needs to span multiple columns because it's going to fill its parent control which is the refresh view which means i can delete that off the collection view and i can say grid dot column span 2 for the refresh view and our collection view is going to fill that now this is nice because the refresh view is flexible if you can scroll content you can refresh it so a web view a scroll view a collection view a list view all those things now we need to set a few properties here so we're going to actually set a command which is what do you want it to do and call when pull to refresh happens and we're going to say binding here to get monkeys command all right and then we also need to control that pull to refresh we have a little indicator right now running but we probably want to tell the refresh also to stop because we're going to pull it's going to be active and we need to manually tell it to stop and we can do that through data binding so there is a property called is refreshing and it's true and false but i'm going to do a binding here to a property that we haven't created yet called is refreshing all right and you can see those little dot dots come up so here's what we're going to do is we're going to come over to our monkey's view model and we're going to add another property this time bool is refreshing and then we're going to say observable property just like that we've created our data binding in place and now we have the option right we have the option of controlling when do we want it to stop do we want it to stop immediately like is you know is uh is refreshing here immediately false is that what we want to do that could be we might have a little our own little animation playing or something else like that we just kind of want to be notified now we could do that um but let's also maybe think about doing it in a different way which is maybe we do want to pull the refresh we want it to stay as long as refreshing the data so we can put that down in the finally basically is busy is false is refreshing as false they're saying well james why don't you just use is busy here right you already have that set up well the main problem in general here is that as soon as you pull the refresh if you did data bind into is busy it would be true right so if i actually had a break point here and let's spin this up over on android for example you can see exactly what i mean which is that data binding that we put in place for is refreshing that would automatically be triggered to true so we don't really want to use that then as the property that we're gauging if we're able to refresh or not so here i'm just going to do a pull to refresh boop and notice our is busy is false but our is refreshing is true so now i can continue on load our data and sure enough there are monkeys and that little puller refresher is going to be right on top which is nice now if i come over and actually run this on windows we're not going to see pull the refresh unless you're on a touch screen so there's a few ways of getting around that if you want to you could obviously have your get monkeys over there but you could also add toolbar items these are super convenient because you could come in and just say text and then say refresh and yell at them and you can add an icon and if you save that there you can see there's a big refresh button right there in the top right so a lot of different ways of doing that you can do the pull the refresh on the collection view or you can go and add this refresh as well which is really really nice all right all right now that we have our refresh view what if we wanted to sort of organize these items in the collection view a little bit different that'd be pretty cool right now we just have this vertical list that we have scrolling up but wouldn't it be cool if we could do grids and columns and horizontal and vertical well we totally can so let's go ahead and push this over here and what i'm going to do is come in i'm going to add another property to this collection view it's going to be the items layout there we go which is pretty cool now there's a whole bunch of things in the collection view like sizing strategies and all these other things but items layout is pretty cool it enables you to use a built-in items layout or your own custom one so there's a few built in such as the grid and the linear and by default we're using the linear here which is like really really cool but you can set the linear and you could do orientation of vertical or horizontal but i love the grid so if i do the grid items layout i can say orientation vertical to still go up and down and then i can do something like span there's different spacing there's different things inside this i could say span and i can say give me 2 for example this is going to now assign two columns in our application whoa that's pretty cool now i've added this the padding here on the grid but if i wanted to i can now remove that and let the collection view itself handle it i'd remove a view from it which is actually quite nifty i could also make it three check that out now i got three just hang out right here right now i don't want to optimize my controls and my views based on this but in your mind you can sort of set that there the other thing that you can do is you can do something like an on idiom for example or you could do on platform you could do on android do three on ios do this i could also for example say yeah on idiom desktop one and then default uh three right so now when i'm on desktop it's gonna give me one it's gonna give me more information but maybe on mobile i want it to be really condensed so now if i come over and i should pull up our windows device over here and just hit debug we're going to see that on desktop we're going to get just one whereas comparatively when i ran it over on android on there i got the three of them so here we go refresh and we get one so you have control over what you want to do there which is really really nice now one thing that has always bothered me and i'm sure it has you as well which is when you launch this application you get this big blank screen that's not great what we want to do is put in an empty view basically says hey when this thing is empty would you please you know show something right it could be an animation it could be just like you know an image for example and you have control over doing that so let's go ahead and delete this items layout we don't really need that anymore but let's go ahead and now come in and say collection view dot empty view now with that alone it's going to enable me to put any view inside of it so i can put text i can put images i can do anything so let's do this let's put in a stack layout and i'm going to put and make this i don't know vertical option center horizontal option center so put it right in the middle i'm going to say you know what let's just make it like i don't know 200 by 200 so width 200 height 200 let's make sure we do that and now what i'm going to do is i'm going to put an image inside of it so i'm just going to say image so what i've done is i snuck over a little sasquatch he's like hey how's it going i'm just a sasquatch hanging out i'd love to be in your application so let's put them in the applications i'm going to say source nodedata.png and then what i can do here is i can say horizontal we'll do center and expand vertical center and expand and let's do an aspect of aspect fill all right so let's go ahead and rerun this over on windows and now what we're going to see is that our application should now have our little sasquatch oh there's a little sasquatch pretty cool now i've just centered it over here so we can actually center and expand and it'll fill it all up but when i hit the get monkeys sure enough boom there is our monkeys totally ready to go which is really really cool if i run this over on android we're going to see the same exact view that we saw earlier so let's go ahead and boot that up and we should see something similar and you can of course tweak the view as well if you want to which is nice so let's go ahead and see what this looks like over on android here we go let's pull this over here sure enough there's our little sasquatch hanging out now you can also delete this as well and i'm just going to go ahead and we're not in hot reload so what i can also do is i can say empty view there's an empty view and an empty view template i could also say empty for example here and if i rerun this now i'm not going to use any you know custom template i'm just going to go ahead and use the text here that is empty so now we just see empty so you're kind of in control i like that you can just put a string but probably you want to put a full control inside there that would be the most ideal scenario but there you have it we've optimized our collection view we've added an empty view we've played around with different stuff and at this point you sort of discover some of the really cool features of the collection view and the other controls that play real nice now the last thing is really taking a look at how we can optimize light theme and dark theme in our application and how to reuse resources throughout our entire app so stay tuned for the final module in the workshop all right we have now come to the final section of the workshop specifically we're going to talk about app themes and resources and how you can optimize your application with less code with reusable styles and also do theming for light theme dark theme or your own custom theme as well now this is one of my favorite parts of donna maui because now in the default template there's a default style for everything that's built in so it's really really super optimized which is absolutely delightful but inside the workshop we're going to see how our application today is structured to not really be flexible for that light and dark theme we're going to go ahead and implement that ourselves but before we get there we've actually been using a bunch of styles and themes i just didn't tell you so i think it's good to go back to the basics and break down exactly what is happening and why you want to use app themes and resources and styles so let's talk about this the objectives of using styles and themes that we want to avoid duplication of xaml or any of our resources we also want to create a consistent ui make sure our resources and styles are available across the app and also we want to enable light and dark theme modes so let's talk specifically about those motivations first we think about it right here we often might be duplicating a whole bunch of xaml over and over again if you look at this code here we have a label entry a box and a button we're setting the background color over and over and over again to different colors such as white and black and we're setting the font size here to 16.5 and that's a hard-coded string if we want to change that we're going to have to modify it on every single control which is kind of like a bummer now of course you could probably do some different refactorings and different things like that but it's not going to be super elegant what you really want to do is create something that is less error prone so for example wouldn't it be great if we could just set a resource that would be defined on these objects that can be used in multiple places so for example on that label and button we have that specific color for our text and background of 0 0 ff00 and that font size of 16.5 what we'd want to do is apply resources throughout this ui and the entire application and we can do that because built into donna maui are resource dictionaries you can think of them as key value stores that enables us to customize our user applications interface so normally a resource dictionary is a bunch of objects it says a key and it has an object associated with it so for example you can add and remove and get index in on different resources and they're returned to you automatically now we can create those encoded c sharp or inside of xaml itself so what i like about this inside of a resource dictionary is that it has a bunch of objects inside of it for example we could set the thickness or a color or an integer or anything really to be honest with you here what we're going to do is we're going to create a thickness maybe we're using a padding here inside of our xaml markup we're going to give it a key we'll say my key and we'll set different values so 10 20 40 80. that's going to be left 10 top 20 right 40 bottom 80. and then we can reference that later on so for example what we would do to access static resources is put them either in the page or inside of our app right here and then use them by referencing them below here i'm setting the padding to the static resource of my key so this enables us to bind basically our resources to specific properties and if i change those values later they'll cascade to any of the different controls that are using that now this is great because there's a bunch of different things built in such as any of the different you know settings like thickness or color of don and maui but you can also use standard types such as strings and characters and singles and doubles and bytes and hints and booleans as well you can set them all here which is actually really really nice use this x colon which is a reference to the specific system and you can just go ahead and define those and set the keys as well so if you need to pass things across you can define those two another nice thing that is built into don and maui is something called on platform this enables you for example to set specific colors or different values based on the platform it's running on so ios android mac windows you can set those different colors and when you bind them up it'll automatically find the specific value that you've set that's super duper nice now one of the other things that you can do is update the resources as well so for example here i have a background color of blue but you can also update that later you would go in and access the resources of the application or the page grab it by the key and set it to whatever the new value is now this is a little bit different previously we're using static resources and static are static they don't change you'd have to set that to a dynamic resource and a dynamic resource specifically would change and be listening for events so you want to use dynamic resources whenever you think that value is going to change so that is something that's super nice based on what you need static or dynamic you can also apply these resources in code i've been doing it all in xaml but you can see that you can do set static resource or set dynamic resource for any property to a specific string which is nice now styles are also important because styles cascade with those different resources for example here we can see that we have two buttons that are using a lot of the same exact resources highlight colors edge size text color and the only difference is the text now we'd want to optimize this in many many ways because here we're doing a lot of static resources and in fact every time you set one of these over here it's going to be a little bit slower to do that static resource lookup compared to just setting it to white for example so when we think about efficiency if we could somehow reuse and only have to look up things once that would be ideal and that is where different styles come in with setters and a setter is a container for a property and a value pair so very similar to what we're creating in our static resources but here i can create a setter of the text color property that it would bind to and set a value so that means i could create a style of a bunch of setters so here i'm going to create a style of a target type of button now what i'm going to do is set a bunch of setters for all of those different properties that that button would be now this target type is just for the specific button so all of my buttons in my application would use this style because it's sort of a base type there but we could also set a key just like we did on our static and dynamic resources and this will enable me to reference that style later on in my code for example here i now have my button ok and cancel they're both using the static resource my button style now what's nice is that if for some reason i wanted to change the background color of cancel i could still set that and it would override my style which is oh so nice now remember here that you can use static or dynamic values inside of your setter so if that background is never going to change just use a static else if the text is going to change you go ahead and use a dynamic resource too so it's up to you and you're in control now like i mentioned earlier there are differences between implicit styles and explicit styles styles can automatically be controlled by all to all the controls if you omit that x colon key you're literally saying here hey that button is every button inside my application because i didn't give it a name so it's set it everywhere what you're going to do is provide that button style key there like i said you can always override things so for example here if i just set the background color to blue instead of red it's going to go ahead and override it as well which is super nice now so far we've set specifically the target type to button but if you want to you can sort of create a generic one because you do have ancestor targeting so for example every single control is a visual element so if you created my visual element here and that you set the target type to visual element any control can go ahead and reference that for example a button could set the style right there if you wanted to so again you can be very specific or more generic now don't forget you can totally set these things in c sharp code as well so here we can create a bunch of setters in a new style of a target type and you can create them all there in code as well so up to you if you want to use xaml like i prefer or in c sharp 2. now let's talk about light theme and dark themes in applications because now we have a general concept of styles and reusable resources and we could change things dynamically but wouldn't it be great if your application could automatically react when the user changes from light theme to dark theme or you could manually set it in your application well you can because there is another type of resource binding which is called the app theme binding you can think of of it as a theme aware dynamic resource so here for example at this markup extension i say background color app theme binding and then i bind the light and dark settings to different static resources so this is super duper nice i'm still using those static resources or the dynamic resources i've set up so they're shared throughout my application but i use them in an app theme binding you can also use these in styles as well so this is one of the nice things that i like is what i do is i create a bunch of styles for all of the controls in my application like you see here and i set the app theme binding on them so this is super nice because now i can reference just my button style and i'm off to the races with app theme bindings now you can also set the theme manually by default it'll adhere to what the user has set on their device but you could manually set this into light theme or dark theme mode or whatever the user selected and this is nice because you might have a settings screen where you're actually enabling your users to always use light always use dark or go ahead and use the system preferred so let's go ahead and do it let's implement app themes into our monkey application all right we're almost at the end of the workshop we've made it this far now it's really just about fine-tuning the application as we just saw over with the collection view and now we can do the same thing with app themes now i've actually pre-loaded this application which is a bunch of themes but we're now going to optimize it specifically for light and dark theme mode so let's check it out all right so our monkey finder application is looking amazing but here on the android emulator if i toggle on this dark theme mode there's no dark theme that's a bummer town how do we get dark theme in our application well all we need to do is update some of our default styles so we have all of our different refresh views collection views and you've probably noticed that one thing that we've been assigning are these different styles over here and these styles specifically are for things like the labels like large label medium label if you look at this button you saw there's this button outline for example you're probably thinking like hmm that's cool and james styled a few things but you know how do we enable the light theme dark theme mode so let's take a look over here specifically in the app xaml and the app shell xaml so over here there's this shell resource which gives you a bunch of resources for the shell so if you have tabs and fly-out controls you can apply things there but over on my app xaml what i've done is just set out a default style sheet for the app now when you get a new done maui application there's going to be an entire style sheet for the entire application and every single control i sort of paired that down into a minimal viable product here okay so what we have is a few primary keys over here for colors we have primary primary dark and an accent we have a light background and a dark background and then we have a few styles we have a page we have a navigation page here are the labels and all these different things here so if we see well our label is setting the background color of text to this dark color and all of these other labels are inheriting from them so those never update now if we look at this you know button here we have our button and sure enough it's using just a light theme and same thing here check this out if you look at this background it's just using a light theme too so what we can do is start to update some of these colors so let's do something first let's come in and we have our light theme and dark theme but let's add a few other colors so i'm just going to have some new resources and let's do a key here which is what we'll you know call into i'm going to say label text and then i'm going to say that 1 f 1 f 1 f one f yeah that's it cool so that's going to be the normal text when we're in light theme mode i'm going to add another one here which is dark so when we're in dark mode what do we want it to look like we want it to be white for example so we have that contrast now for that card view we also need to add a few properties too so let's do color x colon key i'm going to say card background i'm going to do white because when we're in light mode we want it to be white and then over here when i'm in dark mode here we go key i'm going to say card background dark let's make it another color which i'll do one c one c one e which is like not quite black but like a little bit over there so you're just kind of contrast you're playing around with colors over there now you can see i've defined the background here for a light background dark background so what we can do on this page is actually update this instead of using a static resource we're going to use an app theme binding right so we're going to do app theme binding that we just learned about i'm going to say you know in light mode over here let me just pull that back in light mode let's use the light background so i'm going to say light equals static resource of the light background and then what i'm going to do is i'm going to say dark over here i'm going to say static resource dark background all right in fact you can see i have that in a few other places if we were to add a navigation page over there so we have this in light use light and dark use dark now we're also able to do is update this label now if you remember all of these other labels inherit they're based on that base label so we only have to set this property in one place so again we're going to use an app theme binding and then what we're going to do is we're going to come in and say just like we did before let's do light a static resource to our label text and then dark over there to a static resource to our label text dark cool easy peasy see it's not that much it's a little bit verbose but you know it's going to enable you to do this you put it in one place all right let's also update a few other properties what about this button background well we can actually update this to the let's say light background and dark background so actually let's go ahead and copy and paste this here to this this background that we set earlier so we'll assign those the same colors of our main page background so let's go in here and here's our button just like that we'll put that in there now for our card we want it to be a little bit different we don't want it to necessarily just be the light background it'd be pretty great if we could do and assign that to the um card background right so that's what we're going to do we're going to come in we're going to say a um app theme binding static or light theme there we go i'm going to set that equal to a static resource of our card background and again our dark over to a static resource oops static resource of our card background dark all right just a few different properties over there assigning the different colors so they align well you can of course get those from your designers or figma file or anything like that right you get it there and now what's going to happen is we can come in run this again and ideally what we're getting is all of our themes coming in in real time into our application so let's see the application start up here here's our monkeys boom cool now i'm going to hit this right here and just like that the entire theme transformed over here because we are using those styles that we've defined if i go into this details page over here we have the same button outline we have the medium the small labels they are adapting automatically to the user interface and again if i come in and do this boom the themes are dynamic now we mentioned in the slides that there's normal static resources there's dynamic resources there's app theme bindings now the reason that you don't need to make any of these dynamic resources in this case because they never change if but if you were to be like dynamically i want to assign label text to a different color it wants to be red in some situation you can make it dynamic but in this case i'm just making it static and we're totally good to go and there you go we've just created our monkey application in full force to be light theme dark theme getting stuff from the internet doing geo location and all that stuff we just built our flop and it's looking pretty awesome i love it all right now before we get out of here let's load up our ios and mac application from visual studio 2022 for mac now on windows you could also like i said connect and use the remote ios simulator or you could also plug in an ios device and use ios hot restart to deploy directly to an ios device we're also going to deploy to the mac so we're going to go ahead and use visual studio 2022 for mac this is the final source code so we get our empty view right here we can click on get monkeys and sure enough we get all of our monkeys we can do find closest and just like that it uses the geolocation and sure enough i can tap on a monkey and i'm navigating across which is really cool i can also do show on map which will launch apple maps as well now let's go ahead and open up visual studio 2022 for mac and what i'm going to do is select the mac option from the drop down here i can also like i said earlier select under the ios simulators i'm just going to hit debug now this is going to compile up our mac application using mac catalyst and my mac is in dark mode so we see our dark mode application again we can hit get monkeys just like that we get our monkeys find closest that's going to ask for the location sebastian in seattle very cool and then i'm going to go ahead and tap on a monkey and we navigate across and there we go we've just deployed our ios and mac applications using visual studio 2022 for mac and our application is running absolutely everywhere all right you've done it you've built your very first donet maui application from start to finish you displayed some data and then you learned about mvvm and data binding you pulled some data from the internet and put it into the monkey list you did some navigation and passed data objects around and then what you did is you implemented some native platform features built into down in maui and then you mess around with the collection view styled up that empty view all nice and even added pull to refresh and then add that nice dark and light theme mode to your application with reusable styles this is just the start of your down at maui journey there's tons of great documentation and source code samples that i'll put down all over there and of course i'm always coming out with new videos right here on my youtube channel and of course a bunch of my friends are as well which i have linked down below like gerald um and nick and a bunch of other amazing youtubers and of course don't forget to check out the.net youtube where there's tons of stuff coming up for don and maui and for all the different things you can build with net i hope that you really enjoyed this workshop i loved created it i loved presenting it and i love doing this stuff this is a really long one i hope that you come back and you revisit some of these main concepts that we've discussed here in the workshop and of course if you want more things in the workshop leave comments below of what other modules you would like to see i'm totally up for doing a part two workshop where we go even deeper into different topics and if i do i'll put that down there and i'll link it up over there wherever it is on youtube again i hope that you really really enjoy this i love presenting this type of information and helping others learn how to build beautiful native cross-platform apps with c-sharp and don and maui you have any questions about everything anything at all put them down there and of course if you've made it this far hours into your journey please give it a thumbs up on youtube because that really helps out the channel and of course don't forget to subscribe because i do put out videos every single week right here on my youtube channel thank you so much feel free to hit me up on twitter at james montemagno follow me on github or any of the other places i really appreciate your time and i hope that you enjoyed this learning journey and i wish you all the success in continuing building native cross-platform apps with donna and maui and of course i'd love to see what you work on so please share it there all right everyone thank you so much have a good one and thanks for following along in this donna maui workshop see you later [Music] you
Info
Channel: James Montemagno
Views: 493,181
Rating: undefined out of 5
Keywords: .net maui, dotnet maui, dotnetmaui, .net maui tutorial, .net maui workshop, .net ios, .net android, c# maui, C# android, C# ios tutorial, .net 6, learn .net maui, .net maui essentials, xamarin, xamarin forms, .net maui community, dotnet maui tutorial, .net maui desktop, .net maui getting started, dotnet maui getting started, .net maui example, .net maui crash course, what is .net maui, learn dotnet maui, .net maui full course, visual studio 2022, c#, dotnet maui workshop
Id: DuNLR_NJv8U
Channel Id: undefined
Length: 248min 53sec (14933 seconds)
Published: Mon May 23 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.