Build faster with the Windows Community MVVM Toolkit (featuring .NET MAUI)!

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
so I've gotten a lot of comments lately about the windows Community mvvm toolkit so it's this toolkit that I think helps us get rid of boiler played an mbvm applications so I've used it a little bit and it brings me back to the days of starting an mvvm application I think we've all done this you start an mvvm app doesn't matter if it's a WPF app or a Maui app but you have to spin up all of these mvvm Essentials all this boilerplate so you might create like a base V model that implements I notify property changed you might spin up a base command that implements I command relay commands I know a lot of people use I talk about not using them I might change on that we'll see once we get into the mvvm toolkit and what it does for us but basically there's all this boilerplate that goes into mvvm applications and it's not fun to write it takes time away from focusing on building applications and it's just a bunch of boilerplate and we usually do it across multiple projects every time we start a new project just boilerplate so thankfully a lot of you have mentioned this but the windows Community mvvm toolkit seems like a solution that helps us fight off the spoilerplate and it gives us some foundations so that we can start building mvvm applications quicker and get our get our apps off the ground so we're going to test that out in this demo application so I scaffolded this out yesterday just a simple actually.net Maui application let's spin this up we'll walk through it real quick but basically the main idea here is we're going to apply the windows Community mvvm toolkit to this application and we're going to find out how easy it is to build an application an mbvm application with the toolkit so here we go simply simple maili application so I called this the skate shop we have some skateboard products here some grip tape deck Wheels bearings trucks Etc so we have this product page and this is supposed to be like an image I didn't have time to grab images but we'll imagine there's an image there but the main functionality for this app is we'll be able to add these products to the cart and then come over here and jump to this other page and this car is going to represent all the items that we added to our cart then we can agree to some imaginary terms and conditions and check out so all we have now is the UI I didn't really wanna go into building the UI here because I really want to focus on the Windows community and vvm toolkit and what that has to offer so just built that built the UI ahead of time so yeah let's jump right into it let's use the toolkit not write any MVP and boilerplate and just start building our app focus on our app so the mvvm toolkit it is a nuget package of course so let's install it let's manage nougat packages and let's see I think it's mvvm toolkit we can search for that so there's this old version so we're supposed to use Community toolkit dot mvvm let's find that and here we go the um reading the comment from chat did I ever use signalr I did I actually have a video on my channel talking about signalr I think it was like a few videos where we did a signal our back end as well as a WPF front end I'll have to find that to make sure I link it by the time we end here but that's a good question I do want to use more signal or I build more real-time stuff we'll see so let's install this package community community community toolkit Dot mvvm as we can see it lists out some of the good stuff we're going to get into pretty much most of this here we go alrighty she got the tool kit obviously that's step one and now first part of building an mvvm application what do we usually do if we already have the UI we jump to a view model so let's spin up a view model to add a new item here we have a product View so we're gonna have a product view model as well so we get the class and usually the dreaded boilerplate we have to implement I notify property changed but with the toolkit we don't have to do that instead of creating some kind of Base view model that implements unnotify property changed we can just inherit from observable object that's part of the Community toolkit we can see if we look at this I thought it'd be oh there we go we can see it implements I notify property change hooray and it exposes the classic on property changed method that we're so used to calling so let's see this in action let's build out the speed Model A little bit more so all we're trying to do here let's look at the view we want to populate this product listing with some products so for that we're gonna have an observable collection it's pretty standard of some type we haven't made that yet but hmm I guess we'll call this let's just put it up here for now we're gonna have some kind of product item view model so these are each of the items in our product listing this is a view model as well so we're gonna inherit from observable object quite easy so I see a few more people are joining what we're doing here is we're using the windows Community mvvm toolkit to build an mvvm application and we're not going to be writing out our own mvvm boilerplate because the great part about the toolkit is it provides some Essentials for us and we're seeing that in action subservable object implements on notified property changed let's see what do I want in here so we're gonna need a product name a price and we'll also need a command to add the product to the cart let's add some properties for that this will be the name of the product we're also going to have a price I can make this a decimal and we're gonna need some kind of command do I want to write this yet we'll add this Command right now and this is going to be the add to cart command and we'll probably just take all these to the Constructor for now spin that up and actually we're not going to get into commands yet we'll do that in a bit so let's just gnaw this out for now but overall this product view model gonna be a collection of product items so let's call this products and expose the property for it do I have a Discord I don't that is something on my to-do list I want to get more Community engagement it's been a good suggestion but that is a priority that is planned yeah it would be nice to have a Discord for like Community engagement and just discussing things with everyone that would be nice I feel like the comments don't really promote that enough it's not as easy as something like that like a Discord would be all right so let's initialize this and we'll throw some products in here so let me just copy this I think for now what we're doing is just hard coding them in our code behind we don't want to do that we're going for the mvvm way so all that's going to come from the V model so we can just get rid of all this for now I don't want to do that just paste it here for now so we'll throw some prices on here we'll just do like 9.99 how do you initialize a decimal what do I not say like a d or something I should probably know how to do this oh there we go typical software engineering gotta Google stuff every once in a while even the dumb stuff all right let's roll through this I want to get back to talking about the toolkit there we go that works for now and let's buy into this so wait I'm source a binding to the products there we go so we get all of these product out of view models as the data context down here so we want to bind to each of these properties let's bind to the name for this label and we'll have a binding to the price and we're probably going to format this forget what the exact syntax is to format currencies but we can come back to that and then this button is going to be the command is going to hook up to the add to cart command all right see how this looks we should have our products in the view model it's a good step but the key here was I could just jump straight into getting all this product logic in here I didn't have to spend time initializing some kind of mvvm boilerplate whoops oh we're not even hooking up the views to the view models so let's do that this is actually a cool thing about Maui is we can register view models and dependency injections so let's register this as a transient so the V model products view model so cool register that independency injection and then we can also register the views independency injection injection as well and this is super cool because I want this as a transgender Singleton I think probably transient but this is really cool because you can just pass in the data context up here or it's called a binding context in Maui and we can just resolve that from dependency injection so let's resolve that and this is quite different from WPF because in WPF you would have to like I think it was all of those like data templates where you would map view models to views but this is cool in Maui where you can just register your view or your page and dependency injection and just map up The View model directly in your dependency injection and I guess that's another cool part about Maui is in WPF we would have to spin up this dependency injection on our own but just get scaffolded out immediately in Maui I like that a lot how long have I programmed in C sharp probably like five years I would say probably around 2018. I like it I've done more like JavaScript and typescript lately but I do like C sharp just overall I feel like a lot of Concepts actually relate back to JavaScript it has some functional components in it as well so I like it I guess that wasn't really the question you were just asking how long I've programmed in it but all right so let's try this out again I think the view should map up to the view model this time if not I'm not sure why we'll find out though there we go all right so we got all of our products and these are coming from our view model so that's what we like still need to hook up this command to get that figured out but it's a pretty good start So speaking of this commands when we press add to cart we want to add this we want to store this application State related to our cart somewhere and we wouldn't have this state somewhere so that we can reference it from our cart page as well because otherwise how are the product page and the cart page gonna communicate and obviously we need that communication so that we can get the items we add to the cart over to the cart page so let's start with commands let's actually implement this add to cart command so we can initialize this down here so another great thing about the mvvm toolkit and I've kind of already spoiled it is they have built-in relay commands so you don't have to go ahead and scaffold out some base command or create your own relay command just all part of the toolkit so let's import that from the toolkit and the way relay commands work is we can just pass in some kind of callback and execute something so we'll execute a function called add to cart and let's generate that and maybe we should just test this out for now so let's put a breakpoint here and we'll click those buttons we got on the UI here we go and nice we hit our break point so this is nice create our own relay commands but does anyone really like commands I feel like they're they're a pain why can't I just like bind to a function wouldn't that be amazing what is possible kind of there are some things in the mvvm toolkit that can help us maybe I'll show them off I was thinking about saving them for the end because I think it's amazing but instead of let me bring this back instead of having a command property and like initializing it with some kind of relay command that points to our function we can get rid of all this and we can just use this handy dandy relay command attribute and this in the background creates a command that we can bind to so let's look at this documentation so for example they put a relay command attribute on this greet user function and it generates this great user command that we can bind our UI to so this is awesome don't need to have all this command bloat in RV models anymore we can just decorate our functions with these decorators which I like a lot and I've been one to talk about how much I love class commands or relay commands because I felt like relay commands blue v models but it's hard for me to have that argument with this attribute because there's really not that much bloat and even if you end up with like some massive function that Blitz your V model you could always extract that this some other component if you want to but I feel like this is something I'm going to use a lot I like yeah I see that in chat it is amazing I I agree but let's see this let's put a breakpoint there make sure it works and one thing is since it generates all of this relay command stuff I guess at build time or something you do have to make your class partial so that you don't conflict with that class that's in the background I guess it's not really at build time it must be I don't even know I'd have to do some research on it all I know is this is awesome but let's run this so we're binding too and add to cart commands and all we have is this add to cart function decorated with the relay commands let's see it there we go it's like magic I love it I'm gonna use that a lot all right so now we're hooked up to that add to cart button so we're trying to add a product to our cart but the idea of a cart doesn't even exist in our application so we're gonna need that so let's create a new folder oh what I want to call this talked about vertical slice architecture a lot lately do we want to follow it here I guess we will so I talk about entities in vertical slice architecture I'm not going to go down the whole path of vertical slice architecture here but one entity in our domain is going to be our cart so in here let's have a cart store I've talked about stores in the past but this is basically going to store our application State related to our shopping cart so let's clean this up a little bit figure out what I'm trying to do so basically in this product item viewmodel we're going to get a reference to the cart store let's get that in here cart store this card store is probably going to be like a single instance that we inject through a dependency injection so we are going to get this through the Constructor and inject that later and then we can add an item to the cart so on our card store we'll probably have a function called probably just add the card again let's do that and I don't want to pass this V model to our store as like a parameter here for the item we want to add we're probably going to have some kind of product view model or maybe we'll have a cart item that wouldn't really make sense actually yeah it would let's have a new model in here we'll call this cart item and it's gonna have two properties a name and price and this can just come through the Constructor I like my properties at the top there we go oh what'd I do I've never done that before all right so back to our view model we're going to add an item to the cart and this is going to be a cart item let's initialize that and we can pass in our product name which is going to come off this view model oh I think these need to go through the Constructor there we go and price get rid of all this so that's the way we want this to flow let's generate this method on our store we don't even have that yet and in here we need to add this card item to some kind of collection so on our store of course the store is going to manage our state related to a cart so we need to track all these cart items so let's have I think that's a list we don't need an observable collection because we're not gonna bind to the store in my opinion we should only bind to view models so we're not going to use an observable collection here we're just gonna have a list of cart items we do we can just call this items and the Constructor will initialize this there we go and of course adding to the cart we'll just take that items list and add r called an item there we go nice so kind of connecting things up here it's basically our product view model is moving up and storing data in this cart store and later actually very soon our cart View is going to grab data from this card store so this is like the first piece of the puzzle actually getting data into this store let's make sure we actually have this working oh we definitely don't because we need to register we gotta register this card store so we want to register this as a Singleton because of course this is managing application State we don't want multiple instances of the store because that kind of defeats the purpose of it we're not going to be able to share our cart state with other v-models and that's what we need let's register this as a Singleton all right let's see how this goes oh oh okay we gotta pass the cart store here as well uh oh I want to do this uh we'll just pass the card store I was gonna create like some kind of help or function but I think this is fine for now at least all right there we go this should work now all right got our products let's add to cart there we go we get this data into the store that's a good start and now that we're talking about the store we're close to talking about another mvvm toolkit feature but first we need to create a cart view model that our store can connect to so let's create that cart view model no I notify property changed nonsense on our ends let's just inherit from observable object and now when we add an item to the cart we want to pass that added item to this car view model and this is where Messengers come in so Messengers are another piece of the mvvm toolkit and we can leverage Messengers to basically communicate anywhere throughout our app so let's try this out so after we add an item to the cart within the store we can take the strong reference messenger we can just grab this is like a Singleton that is part of the toolkit you can grab the default instance and what do we want to do we want to we want to send so we can send the message via the messenger so we just add an item to the cart we want to add or we want to send some kind of message that represents something being added to the cart so that message is going to be a class so how do we want to name this I guess cart item added message it's probably good and this is the message we want to send so let's initialize that here and this message is going to need the data about the card item so we just pass that along let's add a Constructor for that this can be this is gonna have to be a property and it can be read only probably should be read only since this is a message that we don't want to get mutated anywhere along the path there we go so we can send that message and ideally our cart view model is going to hook into this message that we send via this messenger it's part of the toolkit handy dandy so we want to register and catch this message in the cart view model so if we want to register to that message how do we want to do this we can just do that in the Constructor let's do that so let's take the strong reference messenger and we want to register for some kind of message I think that's how this works might have to check the docs I think we've seen to register this is that how it works let me check the docs real quick yeah I should actually link the docs in the chat if anyone wants to check it out nvvm toolkit Docs these are pretty helpful yeah cancellation cancellation tokens I don't think I've done much on those that would be a good topic to dig into I'll take note of that thanks Julian okay so the way this works is we register for a certain message that we want to receive so we want to receive this cart item added message oh let's import that and then I believe oh I remember how this works so we do want to register for this message but I think in order to register we need to be an i recipients for the message so let's Implement that interface and that scaffolds out this receive method so when we register for the cart item added message then whenever we send the message that is of this type which we're doing in the cart store then we're going to receive or we're going to execute this little callback here so we should see that in action we're gonna have to hook all this up let's configure this same kind of thing we need to register the cart V model and we're going to bind we want to bind that to the cart View so set The Binding context resolve the cart view model from dependency injection hook that up and let's see uh so this is going to be tricky to test because well maybe not let's try it out all right so let's add an item to the cart and yeah so it didn't fire this receive event or this receive method because we haven't initialized or at least I don't think we haven't initialized the car view model so if we go over here there we go then we initialize it then we subscribe so it's never going to fire this but we can test this if we make this V model Singleton I believe and then pass in I don't think we need to pass in that I think this will initialize The View model and startup let's try it out oh no it still doesn't but I think now let's initialized we can go back right yeah there we go so we received the message there we go there's the item we added to the cart and now we can do whatever we want to it in this card view model so that's the power of the messenger it's kind of like a replacement for I know typically I use like dot-net events to do this messaging between stores and view models so this is kind of an alternative to that instead of firing a.net event from our store we can just go through this messenger and I feel like the interface is a bit cleaner too and it's nice to hook into as well with just this interface and just registering and capturing the message so should the message not be a record instead of a class yeah I suppose it could be a record that would work if we create another message we'll do that make it a record instead we'll see it's a good question so let's see next up we really just need to hook the cart V model up to the cart View let's see how that's gonna work so the same kind of thing instead of hard coding some cart items and code behind obviously we want to bind this to our actual cart let me get rid of all of this hard coding and I suppose on our view model we're going to have a binding to some kind of collection of cart items would I name this products over here so yeah car items it's a good name let's create this all right actually let's not create it let's just copy this error from our product view model for now it's import ant what we need this isn't going to be products it's going to be cart items same with the property cart items I'm not even in the right class whoops that's the message we want to be in the view model there we go so now oh not quite next up we need to actually get some kind of container class because we're not going to have product item view model doesn't really make sense here we're gonna have some kind of cart item view model so we just uh we can just create a v-model uh we'll create it up here again like we did for the other one probably want to extract these two different classes but we'll just throw it together for now it's a car item view model this would be an observable object a couple properties these are probably yeah they'll be read only so we're gonna have a string for the name and it does similar for the price I think is something that we show probably and these these can just come through The Constructor all right let's use this instead not dealing with products here well we kind of are but nice now we can actually do something with this car item added message so we're going to take our cart items and we're going to add a new cart item view model and we can grab all this data off of the message sweet see I think that's what we need uh we still need to hook this up do we still need to hook this up I don't think we do yeah this should work let's try it out oh let's scatter some break points so we can walk through this uh all right so we'll see what happens when we receive the message we also wanna track in the store as well and we'll start in the product view model as well all right so let's add this item to the cart here we go product view model command fires move over to the cart store add this item to our list of cart items and now the messaging so we're going to fire off this cart item added message oh and it didn't get handled because we didn't initialize the card so this is something that we're gonna have to fix so we're gonna have to actually pull all the cart items when that view model initializes but now that that's initialized we can go back to the products we can add an item to the cart go through the same thing again this time we actually receive it in the V model something's null oh and then initialize this collection but we received the car message we attempt to add it to our cart items collection that fails because we didn't initialize this observable collection let's do that there we go oh Julian you're doing some graphql yeah I will say hot chocolate graphql like just the developer experience is super nice compared to I've done some graphql in like JavaScript and it wasn't really that great with like Apollo and stuff so I really like graphql.net that's nice to hear you working on that cool so let's try this out again let's initialize the car at this time so that view model is active let's add an item to the cart go through all of this and there we go our item gets added to the cart although these bindings aren't linking up forgot to update the bindings in The View so instead of item one we want to bind to the name and then over here we want to bind to the price so the way this works is for this collection view our binding source is cart items so that's these this observable collection over here and that contains car item view models so inside this item template for the collection view we're basically binding to where the binding context for each of these data templates is going to be a cart item view model so we're going to have access to the name and the price so we bind to them all right let's try this out again just to confirm that is working all right so for now gotta initialize the cart let's go back let's add this item to the cart probably don't need these breakpoints anymore go back to the cart and there we go the item was added so we got some mvvm communication here pretty straightforward to spin up just had to use the messenger which is a nice piece of the toolkit I definitely like this so that's messaging the only issue is that in order to really show this off I had to make this view model Singleton I actually want it to be a transient and we also had to go to the view model first to initialize it so that we would register this subscription for the car item added message and then we go back and add an item and then it would actually get this receive method would actually get fired but that's not really how this is going to work instead what is going to happen is just demonstrate this real quick basically we're going to add an item to the cart and this receive method never gets fired because the cart view model isn't initialized so now if we go back over to the cart obviously we're going to have no items because we never received this cart item so basically when we initialize the cart view model we want to we want to request all the cart items from the cart store and this is actually another cool part about this messenger is on top of just receiving events we can also ask other components in our application for data so we're going to need another message for that let's see foreign how this works I know we need like a special type of message too request all right here we go so we can have another message let's add another one and what we're trying to do is request all the car items from the store so we'll call this the cart items request message and the special part here is that we want this to be some kind of request message and whatever what do we what are we requesting we want all of these car items so we want an i enumerable of cart item and I think that's all we have to do because we'll see in a second this class that we inherit from defines the property that's going to contain the data so that should be easy to use all right so now we can go back to the cart store and this store is what's going to send all the car items back to whoever's requesting it whoops so we want to see or we want to register to other components or we just want to handle whenever something requests all these card items so we can do that with a strong reference messenger again and we want to register I believe we want to register this cart store to handle the cart items request message and we can handle that in some kind of callback so this message Handler this is a function I guess that takes this card store instance I guess this is like the sender right let me make sure I get this right I guess it's uh let's see this this is confusing I think this is this first parameter is this store and I guess the second parameter is whoever is sending the request for the car items hopefully that's right I think we'll see in a sec when we look at what these types are so yeah first is this cart store maybe I should call it that card store and then who is this this is the request message so I believe this message there we go it has a reply method so what we're trying to do is reply to whoever sent this message with the data that they're trying to get so they're trying to get all of these cart items so we can grab those off of the cart store the items cool so we're handling whenever someone sends a cart items request message something's trying to get all of these cart items into a view model and who's going to send this message it's going to be the cart view model so when we initialize this V model we want to send a cart oh it almost request message it's not what we wanted a cart items request message which means we're gonna have to implement another I recipient interface here we go is that right oh cart items request message let's Implement that or do we just have to send it let me see I think we register and we send so I think we also like send a cart earnings request message it's the server load deal yeah I think we send it so after we register we should put these together we send the message and then we should get data back because this story is going to reply with all the car items let's see if that's the case let's just put a breakpoint here try this out all right so let's go over to the cart view model so we're going to register for that car items request message and put a brief point up here too we're gonna send a car items request message and then here we go the cart store is going to reply with data for that message so of course we have no items in the cart right now but it replies and then we receive the message so we get back all of the car items and we can do whatever we want with them so let's do that this should be pretty straightforward all we want to do is take all of those items and add those to our observable collection let's look at those items what response oh we also need the handles so sometimes I guess a message might not actually get a response so we should handle that accept the message has not received the response then we will just return early foreign Let's see we should also clear all the car items before we add any more because this is basically our reset so let's clear the items and then add the new ones this represents a cart item let's extract this to a helper method so we'll call this add cart item oops wanted to be more like this so we want to add a cart item and then we'll be able to reuse this little helper method down below as well let's cut this out move this down here now we can do add car item and pass in our item all right sweet so I believe oh Julian I I think I do have a video on task completion source I'll have to link that to you as well but that was like that's that's like such a specific thing I do remember doing something with that I think all right so let's add an item to the cart it's not multiple so I had three items go to the cart so now this cart view model is requesting data from the store on initialization and we should receive that data there we go select the message three items in our cart let's add them and there we go our cart has items sweet I like this messaging we can add some more go back there we go very nice see how the messenger pretty nice to use a lot of functionality I really do like this whole idea of requesting data because usually I would have to like actually inject the store into the view model but now we can just go through the messenger I guess uh although we don't it's not really clear that this data comes from the store anymore but the messenger is easy to use so let's see that it's really most of the features with the messenger although kind of have an issue here so we're registering to or we're subscribing to the strong reference messenger and when you subscribe to the strong reference messenger you need to unsubscribe as opposed to it's actually a weak reference messenger and this will clean up subscriptions for you but it's more it's not as performant because it has to track those subscriptions so I prefer to use the strong reference messenger but that means that we're responsible for unsubscribing and clearly we're not doing that here and if you don't unsubscribe you can end up with a memory leak so these cart view models if we go up to the Maui program we've registered this as transient so that means every time we go to the cart view I believe that means we initialize a new car view model let me confirm that so let's go to the cart view initialize the car review model let's go back oh actually doesn't initialize another one that's weird I didn't know that but anyways if you do end up in a situation where you're like initializing and then or you're in you're just initializing like a bunch of view models and subscribing to this strong reference messenger you're going to want to clean up eventually because if you don't you're just going to have all these subscriptions your cart view models are never going to get garbage collected and nobody likes memory leaks so another piece of the mvvm toolkit is the observable recipient and this exposes some life cycle methods so if we override we can see an unactivated as well as an undeactivated so this was actually something I didn't like about the observable object so observable object didn't have any life cycle methods it didn't even have like a dispose method and that's something I do like a lot because I need I usually need to unsubscribe from some kind of event from wherever I'm managing state so I really like how the observable recipient exposes these lifecycle methods because we can do our cleanup in here so for example it's actually cut all these out and move those on to when activated so when RV model activates we're going to subscribe to this messenger and request our cart items and then when we deactivate we're gonna do the opposite we're gonna unregister and I suppose when we initialize we're going to do unactivated the issue here is that we're not really hooking into these life cycle methods right now since these view models are all controlled by Maui we don't have like any kind of custom navigation setup so we're only going to initialize this car review model once which means we really never need to call on deactivated and we'll just call it one activated once when we instantiate The View model but if you are controlling your view model initialization then you can leverage these lifecycle methods to do any kind of cleanup that you need to it's probably the best parts about the toolkit let's talk about some more actually there is more that we can show off in the toolkit this isn't everything so far we've gone through observable objects for an I-95 property changed implementation we've shown off one of my favorite features where is this the relay command attribute turn any function into a relay commands we've seen the messenger and the observable recipient that goes along with it for lifecycle methods that was a lot you can subscribe to methods as well as request data from some kind of data source in this case our store but there is more so let me add an item to the cart because this looks weird otherwise but I want to show off validation so typically in an mvvm app you'd have to use I notify data error info rolled it yourself roll a bunch of like helper methods to interact with all the pieces of that interface so let's see how that goes we're going to add some validation so whenever we check out if this checkbox isn't checked it should catch that with some validation so basically we're validating that the Boolean back in this checkbox is true and we're gonna use we're going to need some validation for that so on our cart view model of course the cart view is where this checkbox lives so let's buy in this checkbox is checked oh you were just talking to a co-worker about the mvvm toolkit yeah I've I just dug into it recently it does seem helpful I want to use it more I have another video where I work where I work walk through it that's gonna be coming out eventually but I felt like we needed this emergency stream to talk about it let me know if you like it or if you've used it much so we're going to bind this agreed checkbox to something on our V model we'll call it I guess has agreed to terms and conditions let's make it nice long and readable or descriptive I should say all right let's show off another great part about the toolkit so I know I was in the middle of explaining validation but I haven't gotten to this yet and this is super awesome so same thing that we did for this relay command attribute we can do it for properties as well so we can just have a property where let's start with a field I should say it's a boolean4 has agreed to terms and conditions so we all know I love the handy prop change snippet that scaffolds out the whole field and the backing or the property in the backing field as well as calls on property changed we don't need that anymore no more snippet because we can just do observable property and we can turn any field into an observable property so what does that mean it means we decorate the field and it spits out a property that under the hood calls on notified property changed or one property changed I should say so this cuts out a bunch of boilerplate I have flashbacks to like the first time I was writing stuff in WPF and I had to make this one view model that had like probably like 15 properties and I didn't have a snippet and I was younger and I just like wrote all the properties by hand and it probably wasted so much time of course now I have to snippet now so usually not a problem but just getting rid of all the boilerplate of calling on one property changed with this attribute is pretty awesome but same thing as with the relay command attribute gotta make our class partial so that we can leverage that backing property that exists in the generated v-model so let's see so we are going to bind to that property that gets generated and we want to check the value of that property when we click checkout so we're going to bind this button to some kind of checkout command let's do that or let's spin up that command in our view model already jumping straight to the relay command attribute although checking out is actually going to be an async task let's pretend we have some kind of async operation and this isn't just some kind of Play application well instead of relay command attribute we can use the async relay command attribute and now we can turn an async method into an async command let's call it this checkout oh is this not true maybe we go like that I could have sworn there was an async relay command attribute is there not oh yeah there is I think so it it's just the relay game man that tribute and this is actually awesome so the relay command that attribute knows that we have an async relay command under here just by looking at our method it seems like at least it looks like I hope so we're gonna find out let's put a break point here and check this make sure this relay commands attribute works for an async method oh you used mvvm light before I haven't used that is this for Adobe PF application I would assume so I don't think there's much prod Maui applications out there but yeah there is a lot of magic going on as we can see with these attributes I feel like those are crazy yeah it is Adobe PF app that makes sense that's exciting cool let's see if this relay command attribute works for an async method boom yeah it does that's awesome cool so now we want to make sure this checkbox is true and this is where we can get into validation oh it's gonna be tricky I just realized one concern I did Envision is oh let's just do it and we'll talk about it but all right let's just go for validation and I'll talk about the concern but for validation we have to inherit from observable validator huh does observable validator have these I didn't think it did I mean that'd be awesome if it did so on activated oh good luck on the deadline dust thanks for tuning in yeah there's definitely going to be an official video coming out but yeah the fear I have here is we were previously inheriting from observable recipient because we wanted to tap in the unactivated and undeactivated but now I want validation on this car view model and I want to tap into or I want to inherit from observable validator which means I can't leverage all of this unactivated stuff that's unfortunate but what we could do is we could move we could have our cart view model contain another v-model that implements all the validation stuff and then this cart view model could inherit from observable recipient instead and basically like our outer view model could deal with all of the unactivated and undeactivated stuff and it could contain another view model that has the validation stuff that's a little bit difficult to explain I'd probably just have to demo it but for now what we're gonna do is let's just comment this stuff out we can move this stuff into The Constructor and we can comment this out I want to come back to this maybe not tonight we'll see all right so we still got these subscriptions that's good but anyways now we have this observable validator that we're inheriting from so we can do some validation and this is the fun part so we're not going to be really dealing with I notify data error info at all which I didn't mention but that's what this observable validator implements under the hood and if you've ever implemented this yourself you might remember and I even have a video where I did this but in the center of your properties you would have to do like a bunch of validation logic which you could extract to a method but you would have to valid you would have to write that validation logic yourself which wasn't really that fun so the cool part about the toolkit is we can Leverage these data annotations so for example there is required there's like max length mid length stuff like that of course for our use case we're validating if our Boolean is true there's actually not a attribute for that but we can roll one ourselves let me see you so there is a way to make custom attributes let me copy some boilerplate from the docks that I linked in the chat let me just paste that up here uh maybe down here I don't want it getting in the way so this is an example custom attribute that I just copied from the docs we're gonna call ours the is Trio attribute so we want to validate that our property is true and this is actually going to be pretty simple to implement probably generic this to be something like an equals validation attribute but all we want to do is check I wish we could just do something like check if the value is true oh we can right I could have sworn I tried that earlier and it didn't work huh cool oh wait I don't know why it's not giving me an error for that because this one's a validation result back and clearly that's not what we're giving we're just returning there we go there's my message there's my error so we can't even do this because there's an object compared to a Boolean we need to actually do full try parse then bull triparts takes a string so we turn this value into a string let's get out of Boolean call it result and check that so if we parse this value to a Boolean and the Boolean is true then that means we can return with validation result success it's going to be a nice ternary big turn area here well not really and if it's not a Boolean like the parsing fails or it's false then we'll return a new validation results and we'll say something like value must be true cool so that attribute should work so we got some validation on this property up here and now in this method since we inherit from observable validator we can tap into a bunch of helper properties on I notify data or info not the base class spells out for us so first we can validate all the properties we could also validate a specific property but this is like our submit buttons we're going to validate everything and then we can check if there's any errors from our validation and if there is then we can just return early but if there's not then we're gonna show like a message box so in WPF we would use message box dot show but in.net Maui we want to use something called display alert and we can hack ourselves into that by doing application current I think it's like application current main page and we can display and alert so in dot net value we want to use display alert because this is cross-platform like this is going to work for all the Mali platforms not just windows so we give a total say like success and then our message will be check out completed and we'll just have an OK button and okay display alert is actually async so good thing we made this an async command let's await that cool all right let's do this let's put a break point all right let's add some items to the cart let's go to the cart let's check out we execute the validation right now we have no errors but we do the validation now we have errors because we didn't check that checkbox so we don't do anything let's check the check box and bring back that break point there we go and now we don't have errors since we agreed to the terms and conditions there we go checkout completed sweet oh this is actually kind of glad this happened so I can talk about it this is like the most annoying Maui bug ever I've seen this so much but like the the disabled States for buttons for some reason just up here out of nowhere like sometimes buttons appear as enabled sometimes they're disabled looks like this one appears to be disabled but you can click it and it still works and even if you bind to the enabled State on the button if the backing property or the backing data on that binding changes your button will sometimes appear enabled sometimes appear disabled just a visual bug but it's definitely annoying and probably confuses users but button still works I guess that's cool let's see so that basically covers everything in the toolkit so I guess some criticisms I had in mind were there was no like State Management solution but at the same time I feel like that's not super important because this is just a library to help us build mvvm applications and I feel like it did that it gave us the essentials the I notify property changed commands it even gave us validation and I feel like messaging is nice and that's something that can make our stores easier to implement so I like that so I feel like if it did Implement something like State Management I feel like that would be pushing more towards like a framework when really this is just the library help us build mvvm applications let us focus on not boilerplate and actually building our dream application as I've been saying a lot I was also concerned that the mvvm toolkit didn't have anything for navigation which is like a big missing part of WPF I feel like and I even have like a bunch of videos talking about navigation but in.net Maui navigation is built in so I feel like that's not really something that the mvpm toolkit should deal with I feel like that should be again more of like a framework decision so overall I'm pretty happy about this toolkit and maybe you don't need to use everything for example like maybe you want to use.net events instead of the messenger and that's perfectly fine I think even in the toolkit documentation they're like just take what you need so don't know if you use everything and I feel like these things are worth using like observable object don't have to spin up on notify property changed anymore observable validator is like super easy to use I feel like dealing with odd notified data air infos a pain sometimes and all of these attributes are just awesome it makes our lives so much easier don't have to focus on all of the bloat Envy models for observable properties and commands these attributes are pretty dang sweet I will say so yeah not much on the criticism side I'll probably be using this a lot instead of that mvvm Essentials package that I usually use that had all this stuff I'd rather just use the nvvm toolkit because I have some more to it and it's more battle tested than my own personal module I will admit but yeah just to summarize we used observable object got I notified property change implemented we were using relay commands but we went back to using this relay command attribute instead so we could turn a function into a relay commands we also did a bunch of messaging so we send messages to subscribers so we send this card item add a message to our cart view model and we can handle that by implementing the irrecipient interface where we can receive specific messages and then we can also request messages from or via the messenger so we can send this cart items request message we handle that in the store and we reply with the data oh anytime two five and den three glad you enjoyed it but yeah that's pretty much it with the toolkit let's see if I missed anything oh and validation is another great part of the toolkit so we can just inherit from observable validator and have I notified data or info so finally no more boilerplate I feel like I won't be wasting my time writing out mvvm boilerplate anymore and hopefully I can apply this to your own applications get rid of MVP mvvm boilerplate and try out the mvvm toolkit if you want to check out the source control that is I believe Linked In the description I'll push up all these changes to that as well I might clean up this stuff a little bit but yeah and vvm toolkit super exciting consider applying it to your own and vvm applications Maui WPF doesn't matter let's get rid of boilerplate thanks everyone for watching see ya hopefully more live streams in the future as well have a good one thanks
Info
Channel: SingletonSean
Views: 11,007
Rating: undefined out of 5
Keywords:
Id: omo1kzRGK_M
Channel Id: undefined
Length: 82min 42sec (4962 seconds)
Published: Wed Jan 25 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.