C#/WPF - Learn MVVM with the .NET Community Toolkit

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
okay everyone welcome back um i'll apologize up front i i am getting over being sick earlier this week so i've been telling people i'm at a solid 90 so we'll see how far 90 gets me today um okay long list of updates of cool stuff so there's a lot of cool stuff so uh first and foremost uh latest visual studio is out uh so it's too tight uh welcome back jared i've never about 25 um so latest visual studio dropped it worth noting for people who caught my stream um two or three weeks ago where we ran into the issue of when sdk 6.0.302 i believe dropped there was a bug in wpf where if you used a project that had source generators you just failed because the source generators were being added double that bug fix is not in the latest update um so same fix as before there's a little targets thing uh for people who want to see uh here uh 17.00 uh that is a good question let me just launch mine because i i literally finished installing it uh about 45 minutes ago so uh 17 4 is the preview that's out um i think the uh non preview is do yeah 17 3. so 1740 preview one typically what happens is as soon as they release a full release the preview versions immediately bump to the v next just because reasons so these things i imagine are probably very close to uh in sync with the exception that the preview one obviously has preview features turned on and yes it will be a wpf knight um so i run the preview builds because i like playing with preview features and at least while streaming i'm not too concerned with bugs but as you saw i have both versions installed because occasionally the preview builds stuff just breaks and occasionally i just need a stable dev environment to go back to so i have them both the you can have them side by side they do work just fine um variety of explicit versions they're always ready uh that is a great question i do not know so i haven't been over the release notes um too closely from what i saw maui was the big announcement is rather than having to be on a preview vs to have the built-in uh templates for maui it's now just in the box huzzah it's been ga for a while i i don't know why visual studio took so long um yeah there's a there's some small quality of life improvement stuff in here um but not a again there's just little things like highlighting your selection huzzah all in one search huzzah and a lot of these things here um i sometimes miss when they get released because these things have been on in the preview one for a while so yeah yeah i can agree with that um that statement that there didn't seem like there's any anything that new in here yeah it's a lot of it's a lot of little quality of life stuff i will say the innumerable visualizer i ran into this one the other day just kind of by accident went oh that was kind of nice but it's one of those until you're inspecting an enumerable in your debugger so there is that um another thing that dropped uh get kraken eight eight eight oh so i realized it's hiding behind my picture i'll move it up there right there it ain't 0 dropped um the the cool thing so for people who who care so there's a whole list here i'll just release notes if anyone cares um so there's single sign-in which is kind of cool workspace kind of cool this one here partial stash this one makes me really excited so before and get cracking all you could do is stash all pending changes and so you kind of got into this state where you would manipulate your pending changes just so that you could stash it's like now what you can do is you can just go file by file um or select multiple files and stash those and pop those so it makes it a little bit easier if if you are frequent stashing like if all you do is stash to switch off to go work on something else then come back and pop not a big deal right doing the whole thing is what you do most the time anyway but occasionally it is nice to be able to stash like subgroups of changes so that is now there is now a gui for it you know obviously you could always do it on the command line if you wanted to lots of ui updates um nothing that got me overly excited the sso stuff got me really excited um this one will only affect you if you were on teams or enterprise if you are on just a individual account even if it's pro this doesn't affect you so this is more around people with bigger teams being able to easily manage groups of users which is what excited me because there are some companies where it's very nice to be able to have say an aad group where you can put all your users in so i want i was going through the docs on this i may end up just doing a side video on setting this up at some point because this this actually really interests me in doing this and their docs look fairly good but i don't know i make videos so there's that uh okay update update update update ah one last update uh so anybody who was following my uh scurade project uh from the last two streams that is now out and it is actually working so uh see i you i can almost spell the name of my own project very close so for anybody anybody who is tracking the last couple streams this is now out and working there's a lot of interesting stuff jared thank you for following no i'm surprised you weren't already um the i got the auth plugged in so there's hmac authentication for updated releases i got the cli app in a very nice working situation i added off to the api using azure ad for creating new apps so that anybody can't just arbitrarily add new apps to my server because i didn't want that to happen new twitch account sorry for the distraction uh you're good jared um so all of that is in and working and the simply budget test app that i was playing with actually ran through and worked great i was rather impressed uh he doesn't follow until after he gets to be on stream with somebody i mean that's a really slow way to add followers but if that's what it takes sure so but this is out so if people are interested in it i there's still lots of to-do's and a handful of hard-coded things and a few places where i know channel isn't being appropriately used and all that jazz so i want to clean this up but my hope is that the next stream that i do on this will probably be uh hey here's how i add apps to my installer stuff because i got it down to where it's it's darn stupid simple like after the setup is done and i realized that i am a hand weighted moving over a big amount of work but once the setup's done and the nuget package is added you run dot net publish and you're done and that does everything it gens the new installer files calls the server to update the release publishes the artifacts it does all the stuff and i went oh i like this i like this that means in my pipeline it's really easy so i was really happy about where that landed okay now on to other stuff so a very long time ago like around july 18 2019 i made a video and i've pointed several people to this video because i go over the basics of mvvm and wpf you can probably tell by my my my my dirty office background and this door no longer exists and yeah um all of this stuff this is now uh kind of dead and dead and gone um but the this video covers a lot of the basics in mvvm and wpf and there's absolutely nothing wrong with the content in this video aside from the fact that it's really really dated like really dated um and specifically at the time i was using mvvm light because that was my mvvm library of choice and since then there's been a handful of times where i've pointed people to the the microsoft mvvm toolkit which is a wonderful a wonderful library um and it it is i i believe i've told people that it's the spiritual successor to what mvvm light was um it was built from that api and has been redone multiple times over it's been great um but i've been wanting to build an update to this for a while because there's a lot of advancements that have come so specifically if you are familiar with the microsoft mvvm toolkit this is great and the one thing that bothers me is this thing's now technically deprecated but you won't get it if you land on the like the basic page here what is out now and what they have renamed it in so if you go here and you just follow the the nougat package um uh you end up here and at least in nougat they did mark it as as deprecated than legacy it's no longer being being tamed don't let this big scary thing scare you what they did is they renamed their new get package so it's no longer microsoft.toolkit.mvvm it's now communitytoolkit.mvvm for whatever reason i don't know if there was some back and forth with microsoft or what what the deal was because the the people managing this largely work for microsoft like you'll note microsoft toolkit right uh and there's a good method to method table of what methods from light map to the toolkit methods which is helpful sorry i don't i must be out of context for that comment i will trust you um so what i would like to do is actually go through and do a similar getting started with wpf and mvvm but doing it with the new um community toolkit mvvm package so for those people who are interested here is the handy dandy link let me fix the localization on it boom um this is the docs on it for people who are interesting and the the most exciting thing about it or i should say one of the the cool exciting things about it here's the here's the announcement so this this edo release the this blog post came out on the fourth so this is fairly new so if you haven't seen it don't panic it hasn't been out for that long it's a i've known it's been coming for a while but this thing is we'll wash it out let's clean that up a little bit um but this is a fairly recent announcement of what they've done and a lot of what is built in here is heavily powered by source generators so the which is both good and bad it means when you're writing apps the amount of code you have to write is a lot smaller the drawback is that means there's magic and i kind of want to explain the magic so that people understand what things are going on here right and so they they kind of call out the the libraries that are in here we're going to focus on the mvvm one um at some other point we may we could double back for like high performance or whatnot if people find that stuff interesting but that's what tonight will be is uh an introduction to mvvm for people who may be new to this and then for people who are already fairly familiar with it um there's going to be a lot of stuff in here covering the new library and what i would say are cool updates to normal patterns if you're building uh mvvm libraries so let's start with uh there's a good migration guide of what the equivalent methods are ah thank you thank you thank you my greeting from mvvm light perfect i will save this link and add it to the uh the youtube description later and i believe for the most part the upgrade um up to the community toolkit is fairly easy i i think a lot of it is is name spaces and similar uh so not overly not overly problematic but it is it is a major release update okay so for people who are just getting started let's go through we're gonna just spin a brand new wpf application so wpf app next uh app seven that sounds great and yes we will use net six and away we go so uh for people who haven't heard the phrase mvbm before what it stands for is model view view model and the idea here is set uh segregation of what code goes where so the view is your xaml so in in the basic app where you have a a window this xaml guy this main window class this is the view and the code behind the c-sharp file that goes with the xaml is also part of the view and the you could certainly go through you do not need to build a wpf app with mvvm you do not it is highly recommended and you'll see some people online going as far as to say required because there are certain features inside of wpf that are really built to take advantage of it things like binding to a list of objects is so much easier with mvvm versus writing all that code yourself it's kind of a it's kind of a pain in the butt now with that said you'll note there's a view and you'll note the other two things uh model and view model don't exist here and this is the unfortunate part is when wpf shipped those things weren't really in the box so the idea is and what we're gonna focus on tonight is the the view model and the view the the model itself is usually what you can think of like database access maybe services downstreamy stuff that your app uses and for this we're going to focus on just building out a view and view model because often times that's where people uh struggle the most getting started so step one first of all we're gonna update this template to latest c-sharp and we're just gonna clean some stuff up let's see it's been karnak too so for anybody who's not familiar with it file scope namespace and then once you do that you can literally just delete all the usings that's wonderful okay so we have this and we have our our xaml thing here so the first thing we need is we need a viewmodel class so we are just going to spin a basic class called main window view model and then we're just going to move it into its own file and away we go okay and we will do public string uh first name that look at you look at you go co-pilot you're actually writing useful code for me co-pilot uh now admittedly i was sick and taking cold medication but co-pilot was impressing me and maybe it was the maybe it was the medication maybe it it was co-pilot being awesome or maybe it was a combination but it it was rather impressive some of the suggestions it was coming up with okay so we've got a first name property and now the question is this link between it now a couple things i'm going to call out a lot of times when people are talking about mvvm you will hear people say oh don't put anything in your code behind ah this is bad bad bad bad that is in my opinion wrong um the code behind file is very valid to be used that's what it's there for it's designed to put code behind your view so if you need to register for an event like hypothetically you know if you want to do something when the window is loaded right that's fine write some code in here the important part is that the code that's in this code behind is view code so everything here should be related to the view the way your application looks works when somebody touches it and clicks on it and punches it hopefully they aren't physically punching it um that code lives here the moment we start talking about the logic of what should happen when they do that so like when somebody taps on a button what should that do well that that's now moving into view model territory and the idea is view code is really hard to test and i will emphasize this um one of the big advantages of mvvm is testability and some people will hate me for saying this if you aren't writing tests you're missing out on part of the benefits of mvvm right because if you aren't writing tests you can slap everything in the code behind and the whole reason for segregating it is because the view code is nearly impossible to test to actually test a ui object requires like an sta thread and rendering pipeline and there's whole libraries built around testing ui objects it's hard it's clunky it's not fast and most of the time what you want to do is write tests around your logic when when the user clicks the submit button doesn't send the username and password to my service great that that sounds like a test i want to write but if that's all coupled inside of like a button click handler in here that's not easy for me to test hey papa show thank you for the follow um now once we get into the view model and start segregating that logic out view models are designed to be testable and there's there's kind of this blurry line a little bit so a view model's job is to support the view whatever your view needs to function in terms of data your view model should serve that up and make it pretty for the view that's its job its job is to support the view the view model should be agnostic of the view though so the oftentimes i'll see people do things where they leak data from their view model up to their view so you'll note i did something like first name here if you see something like public int window width right there's that or if i do public uh what's a what's another bad one that i occasionally see slip in um thickness right uh button padding right right perfect code equals no test needed correct um in both of these cases well for example in the the button padding i've now taken a class that normally lives like for example if you have to have system windows inside of your view model you might question if that's a good place for it because when i expose up something like button padding i'm now very tightly coupling my view to my view model because that that property is now making a very strong assumption about how it's going to be used in the view and so one it's got a view type object in here and it's named very specific for view this one up here doesn't have a view type object it's just an end but it's still very coupled to what this is and there is a blurry line here about what's appropriate what's not but in general what i usually tell people is the view model should serve up the data and then the view may need to massage that data a little bit ideally as little as possible but occasionally you want to serve up some information from your view model and let the view do work for example colors for theming right i often times will say okay i may serve up a color in my view model and then use a value converter to convert that color to a brush and use that for a background color elsewhere something something to that effect but let's actually let's actually show some of this work so inside of this we're going to do text block text binding first name and you'll note right away so a couple couple features that should be apparent this doesn't work but you'll note i'm starting to get a little bit of uh intellisense so normally i turn the xaml designer off immediately however they've started adding some cool features to it that kind of make me reconsider so you'll know whenever you see these the the little light bulb or the the dots under your code like what you see in c sharp the xaml designer is starting to get some of that same magic which is pretty cool so if i go here and we hey oh are you you don't have an auto complete oh come on one of you guys is supposed to have a light bulb let me try compiling real quick and see if it figures it out i thought it had a light bulb to do it to auto add it for me come on where are you don't don't make a liar out of me okay at minimum it's at least telling me what will happen so setting the data context uh will enhance intellisense when working with data bindings was co-pilot pain to set up uh not really um it was a pain to get into the beta until they kicked it open for everybody but as far as setting it up it was pretty simple i believe it was just an extension add-on and then i did very little to configure okay so inside of here a common place to set the data context is right inside of your code behind so main window view model and when we talk about mvvm the data context or the binding context depending on your your framework of choice this is the context under which all bindings are going to be resolved so for example this binding is looking for the property first name that first name property exists here and it will be able to look that up because it's going to say okay given this binding look to my binding context or data context find the property called first name and assign that into my text brock great the thing is right here it doesn't actually know it says no data context found for binding but if we actually start this app oh and i guess hang on we should we should assign that thing of value because right now it's empty string that's that's not really a great it's not really a great use case so first name will be uh kevin because that's the best first name anyone could ever have biased opinion by spin and you'll note huzzah look at that binding works which is great because that's what it was supposed to do but inside of your uh xaml designer what you can do is you can do uh you can set the d colon data context so inside of xaml um unlike c sharp where you have using statements where all of the user statements just import all the things in there xaml has namespace includes which is this xmlns but your namespaces get named so every so when you reference something rather than just typing it in in order to disambiguate things you have to say hey i'm using this type from this namespace and you'll know one of the namespaces has no alias this colon variable at the end so things like grid exist in this namespace but things like this data context property exist in this namespace and the d one this is one of the built-in ones that is auto added for you when you create it this is largely you'll see it's referencing expression blend this is largely around you can almost think of it as designer is largely what this is for and so if we go here we could go d design instance and we could do your close co-pilot you're close we can then say okay your design instance is first name and now now that the example designer knows the the data context for the bindings when i go through and look at this if i start looking at what is in here you'll know first name now shows up auto-magically right alongside my other properties because now the designer's been given some context about what to bind to which is great okay so let's go through let's let's expand this out a little bit so we're going to do some grid row row definition [Music] uh let's do height auto uh height auto and then i'm just gonna size some stuff okay uh let's see vertical alignment center horizontal no no don't help me don't help me you're doing so good horizontal alignment center see type it's hard i'm going to zoom this in so you can see how this doesn't have a lot of stuff uh to work with at the moment like empty okay so let's go through and we're going to add a button in here as well uh and then that's interest so you could tell co-pilot not that bright uh this isn't valid um because it's trying to do a binding to the an event um no that co-pilot's great co-pilot also occasionally just makes stuff up which is just just awesome okay so we're gonna move this button down here the next thing with mvvm because this text block is great we can get data out of our view model into our view but now we want to actually have interaction because the unlike some other patterns like mvc where uh it's oftentimes pushing stuff out and then registering for events from the view uh there needs to be that interaction coming back from the view into my view model the user does a thing and again it is very valid if we decide that hey you know on mouse uh enter i need to do some work it is okay in your code behind and i'm gonna get rid of this data con uh no that data context is going to say it is very okay to do something where i go oh okay let me grab my data context and invoke a method directly on it from an event handler this is valid this is very valid because sometimes the the stuff that you need to do inside of like events or maybe there isn't a nice binding target to work with it's okay to use this it is okay to use the code behind as long as the code that you're putting in here is view related code and when it's not you put it inside a method in your view model and you invoke it there okay just so we're clear on that detail okay but the standard way of actually getting uh interaction going back and forth is to use what is called a command so we can go in here and we will do a binding click command and i'm trying to remember do you have the auto code button one of you is supposed to have an auto code yes robert it is so a command in order to do the binding so public i command uh what did i call that thing click command and that's probably a bad name because i'm exposing what the thingy that i expect to do and we will go ahead and include this so in the box in wpf you get the i command interface but wpf out of the box provided no well provided no mvvm uh implementations of i command is it legal to call something from a code behind from a view model generally well i got to be careful how i say this yes you can certainly do that so the there there's a couple ways to to do that like if your view model say has an event your your code behind could listen for an event and respond to that as well um in general though i try like i try to avoid like passing like mouse event args down into my into my view model oftentimes my code behind methods will massage the ui objects into something that's not a ui objects and pass the needed data down into my viewmodel or there could be like there there are cases that i've done where the view model say raises an event the code behind watches for it takes that event and does something with it that's fine uh called methods or fire commands yeah in general hey cody vide i appreciate the rate uh so at least in terms of going back and forth lost my train of thought so yes it is it is valid to do stuff in your code behind from the view model the one thing that i usually am a stickler about is making sure that you don't put view code in the view model and view code i i loosely would define as if you're inside of the system windows name space or nested below it you're probably a view class probably there there's a handful of exceptions that i don't mind too much like uh point or size or some of the strucks or kind of okay like it's kind of a bit of a gray area because those things they're they're structs so i i could be persuaded to uh uh i i could be persuaded to let those things flow into the the view model have been a while since i've done client wpf so i figured i'd pop in awesome great uh searching the visual tree is a bad thing to do in the code behind so searching the visual tree usually bad um often so so the the easy option is if i need to like for example if i want to manipulate this text block in my code behind for some reason like say i want to set the background color of it the the thing that you do is you do an x name on it and i call it you know my text block and you spell block correctly because that's important um when you set an x name on it one of the things that ends up happening inside of this initialize component method that gets generated is it actually will create a a backing field for you called my text block so now you can actually come in here and go my text block and just use it right like i can now i can now go muck with its background if i want uh do i need to hide these calls behind some interface view model i add thing or can i access the view model itself i usually just access the view model itself because the view should in in nearly all cases i have no problem with the view knowing directly about the view model like quite often if i need to do a lot of view model access i will do something like this where i go view model and do something like just so that i don't have to type cast my my data context every time i need access to it it's not a bad thing but this way i've got a strongly typed thingy and sometimes you can even you can even do something like this if you if your if your data context changes more than once i mean sometimes i've done this before too just so that this property always looks it up rather than just getting assigned either ones either one's fine for the view to reach back across okay uh okay so back over to here uh so what we are going to need to do then is actually provide an implementation for this click command because what we've done is separate out uh the actual part of clicking the button from what should the button do and in this case i'm going to declare that the button should change the first name to robert because robert is probably the second coolest first name that you could have ish um now the so because there is not a built-in thingy i am going to go and grab the let's see mvbm search probably near the top nope uh community toolkit uh you're welcome robert uh so you'll know this one scary warning deprecated use new name but again it's it's basically the same stuff they just renamed their nougat package mountain dew robert is speaking my language robert is speaking my language so um every mbvm library worth its salt comes with some implementation of i command all of the libraries that i like to show off uh their built-in one is called relay command okay so we do this add this and the relay command edits at its most simple takes in a an action which usually we just pass it a method to uh to tell it hey invoke this method so just kind of by convention and this is this is a a kevin ism not a uh not a well-defined thing i tend to suffix my command properties with command and name their action events starting with on and dropping the command suffix that's that's just that's just me so um and in this case we're gonna say first name becomes robert because that is what we declared it to be come in here we're gonna launch okay note to self we should make we should make the font bigger uh font size i don't know 24. cool you'll note because there is hot reload turned on by default i just edited that without even clicking anything or doing anything in my debugger it's wonderful it's kind of like what web developers have had for years okay so i'm going to set a breakpoint inside of my on click and then we are going to click the button and our method gets a vote huzzah first name currently is kevin we step over first name is now robert we go wonderful we take a look here and our ui hasn't updated now people who have been around my channel for a long time immediately know whenever i see somebody saying hey my my stuff isn't updated there are two root causes in wpf if something doesn't update when you see the property change the two most logical explanations are the uh the property change notification wasn't regis wasn't done or your data context is wrong we already talked about data context what is property change there is a magical interface called i notify property changed uh let's do boom and this interface has a single member an event called property changed and inside of wpf and uh most mvvm frameworks from microsoft that use xaml what when you do a binding and it looks at your data context for this property it actually does a little bit more if the data context implements the or i should say the data context instance if it implements i notify property changed it will actually register the binding itself will register for this event and say ah okay anytime this property changes i should go and update my text property which is great because again if we go back to the idea of testing our view models that means when i'm writing tests against my view model what i'm actually doing is writing a test to say okay when the click command is is invoked did the first name property change to robert great my test would pass the problem is is because i didn't validate that the event was there as well the ui is sitting there going well when i checked the property the first time it was kevin no one told me it had ever changed why would i just randomly update right because this is just an auto property there's nothing magical happening here at all so generally what you will see happen and this is good this is going to become long form real quick so this is this is uh convert to full property all right so if we go to full property so rather than just an auto property we'll get a lot of stuff in here oftentimes what you will see happen is your setter starts to get big and ugly is it starts to be this and then you end up with hey yes oh oh you were so close i didn't tab it right uh let's see properties there you go co-pilot that's the co-pilot i love that's the co-pilot i love okay generally you'll see something like this and now if we launch we click our button oh we hit our break point we turn off our break point we let it go now it actually updates great that's what we expect because now when this event fires the binding that we created right here properly goes ah the first name property has changed everything flows everything everything works the way we expect now because the bindings in your view are watching that event it is important that you don't raise that event too much because every time that event gets raised especially if it's raised unnecessarily like for example if i were to do that that's going to end up raising the event five times and really the value has only changed once so often times what you will see happen in your setter is something more akin to this if first name is not equal to value then we'll go through and do all of this work right and we start to build up and you can imagine if you have to do this logic for every single robert i've got mountain dew here and this one here has um airborne in it i'm i'm dual fisting it tonight uh if you have to do this for every single property that you want to bind to this gets to be really big really fast and kind of obnoxious um so there are i'm going to skip over showing you all the intermediate steps from prior versions of the library and we're just going to jump straight into the coolness that is the community mvvm toolkit so for starters the um observable object for starters there is a base class built into the community tool kit called observable object which is great and if we go and take a look at this guy he's got he's got some cool stuff built into it so one you will notify note that he implements the i notify property change oh thank you robert i appreciate it again uh and property changing seven months wow that's a lot robert um so he actually takes care of implementing the interface that our binding wants and you'll note he has some nice methods in here for you know on property changed and he leverages this caller member name so we can then we can take all of this stuff and we can just go on property change and i'm just going to call this out because this one often surprises people you'll note that this method um takes in a property name string but it's optional and the cool part here is this attribute caller member name if you don't pass a value when you invoke this method what the compiler will do is it will look and say okay who is the caller ah it's the first name property the name of the first name property is first name and it will what will actually get compiled is something more like this which works great so that is a nice clever feature but it also means that if i don't specify that string if i ever rename this to be you know i don't know first name two this will still magically work and it'll raise the appropriate property because the compiler will automatically update which is great but we can actually get even better than this because this pattern again it means i have to have a field it means i have to do some checks i have to assign i have to raise property change and yadda yadda yadda yadda yadda that's typing that's a lot of stuff and we're going to skip over the history uh ignore that we're going to come back to it in a minute so you'll know their example here looks remarkably similar um we can actually get really cool so you'll note we can get a lot smaller than this so and i will call out on theirs they've got a full name property because occasionally what you want to do is when first name changes well you'd want to raise property change for first name that's a given but if you've got a composite property like full name you want to raise property changed on that as well because those bindings they don't know anything about if they're bound to the property full name unless they get told hey full name changed those bindings don't do anything without being told and this set property method this encapsulates the check if the value is different raise the event if it is that's all this is doing but you'll note we can take all of this logic and we can boil it down to just this so let's try this because this is quite frankly awesome so all of this all of this stuff here right gone and the one thing that we do have to do is we do have to make this a partial class so it's important to note with source generators what ends up happening is they generate an extra c sharp file conceptually behind the scenes that's going to get compiled with your project now with c-sharp you can split a class definition across multiple files as long as it's declared as partial if it's declared as partial this class definition can be spread across any number of files and source generators take huge advantage of this so if you want to use these cool source generator features you do need to make sure that you make this thing partial and i believe if i remember correctly yeah you will get a a flag here and then i thought they had an analyzer for this but apparently not this is just the straight up compiler making an argument because right now the compiler seen two main window view models mine and the one from the source generator and the problem is the source generator one has the word partial and mine doesn't it's going ah that's that's not right the other one had partial did you miss it oh boy hence the airborne i've been talking too much okay we slap this partial on now if we want to look we can come in here we can pop open the community toolkit source generators and i believe if we come into here let's see observable property generator it's probably this one and you'll note here's a c sharp file and we can click on it and we can see everything that it generated for us and you'll know from that first name property it's actually gone to the effort of hey let me create that first name property for you hey let me do the appropriate um equality check to see if those two values are different and then i'm going to generate up a um some some uh partial methods so partial methods will either if you don't imp do anything with them in your version of the partial these things just go away the compiler ends up dropping them because it goes nah they weren't implemented don't care but there are these extra magical methods that just show up so it's no longer a method or a property how do i run additional logic now uh so the answer justin bieber is right here so on first name changing so there's a couple on changing methods that give you some injection points and then there is a on change so it depends on whether you want to run logic before or after the assignment so if you want to run something before the field gets assigned you could do it here uh and if you want to run something after you could do it here it is worth noting that you don't at this point there's no way to like stop the assignment that's not really a thing you could like change the value to be something different or reassign back and double do it like that's all possible but there isn't necessarily a way to say stop it if you wanted to do something like that but that means that over here if i want to go with a private void uh on what is it on first name changing or is it not giving me private void i don't know why i'm not getting intellisense is that the right is that the right name on first name changing oh i didn't here we're just gonna copy this because that way i don't have to think too hard paste drop the word partial boom and drop semicolon okay so now that this guy is here you'll note that this thing is now actually lit up so if we go here um and you'll note my code down here that's assigning to robert i'm still i'm i'm assigning to that property because if i look at this i've got both a first name field and a first name property right which is which is pretty slick um that both of them are there and these are done as incremental generators uh all these attributes so similar to post sharp yes but there's a key difference between these is post sharp did it by manipulating the assembly post compile this one is doing it with source generators which is effectively pre-compile small but important difference um and you can see this the generated source here which in my opinion is just a whole heck of a lot nicer post compile stuff with il weaving is insanely powerful insanely powerful um because post sharp can cheat they don't have to do things with like partial class and all that stuff because they're post compile um maybe that's why they call it post sharp i never thought of that interesting philosophical discussion uh okay so let's fire this up and we can actually see this work uh there were builders what are my builders ah ah yeah see here this this this is the bug if you get a bunch of these already defined already contains this duplicate definition stuff okay so pro tip here come to the material design project or any of my wpf projects because i think i've done it to all of them now directory build.targets this is what you want this target right here copy this is the fix that is going into the wpf thing at some point slap it into your cs proj or directory build thing somewhere that's going to be part of your compile maybe don't call it material design uh dixie watty right all that matters is that this target exists it has to have a unique name and it has to be called before core compile effectively it's going to strip out the duplicate analyzers because they're added twice and now now we should be able to launch oh hush now oh that's a dip uh let's just rebuild and hopefully it picks it up uh let's see main window already defines a member name on first name changing [Music] why am i why am i being stupid why am i being stupid oh i i added the word private and this should have been partial there we go so if we come in here and we click we now got first name changing robert and if we were to look at our first name thing we can see that the current value is kevin so bear in mind i did changing this is the one that is before the assignment and then there's changed which would be after the assignment which is pretty slick so if you want to do any additional logic about changing other stuff or that kind of thing now most of the common use cases where you might want to do additional logic have been handled for you because the common case where you do extra logic is usually notifying that the that the command is valid so for example i i kind of skimmed over this relay command a little bit i command actually has two things that it does first it has a thingy that it can execute so it has an execute method and then more importantly it also has a can execute right if we look at this interface two things and you'll note the can execute also has an event this functions very similar to the inotify property changed once again all of the commands at wpf they don't do anything magical by themselves they go can i execute oh i can okay let's do it right that that's it and if that can execute ever changes later they don't magically update on their own so for the relay command i often do can click right so again just kevin's naming convention private void can click oh not void this needs to be bool because you know it has to tell it uh and it will be you can click only if uh first name is kevin right so we'll just we'll just limit it you can you can click the button once but once you get to robert you've reached the uh the pinnacle of first names and there is no there is no more clicking involved right so if we fire this guy up what we should see happen and i'm gonna kill my break points so that i don't annoy myself is after i click this my button should go disabled but it invoke the and i'll restart this just to prove a point it invoked the can click once on startup and said oh okay i'm able to be clicked great enabled the other so we can also we can invert this logic here as well because if can execute returns false which it should dial because that's the starting value what it'll end up doing is disabling the relevant control that it's attached to which typically means control dot is enabled goes to false i think that's true for every built in control um is enabled goes to false if the command on it if it's can execute returns false now the problem is is if this updates later we want to notify it and oftentimes you would do that inside of like on one of these changing things but conveniently you'll note they've said oh hang on let me help you with that rather than you writing code that goes through and says hey on the command call notify can't execute change because relay command does define a uh notify can't execute change that's a thing that exists we can come in here and say hey by the way i would like you to notify on this guy when this when this property changes notify that this command should be updated again right so we should be able to go back to here and then when we click the button we should see it just go disabled uh oh it's because it wants the generated code for this if we look at it it wants something that implements ireland command and this is only an i command so if we make this an eye relay command that should now work oh and actually we don't even need property changed anymore base class hands up handles all that for us our code's going to get real small real fast we come in here click the value has changed and my button is now disabled because i slapped an attribute on a field all right so real quick this this deserves a round of applause for the for the authors of this library they did an awesome job in my opinion this this is absolutely amazingly slick stuff again i'm going to skip over the the case where it notifies property change for a composite property i think we can imagine how that works um this is so slick so slick i absolutely love this um the one thing i did want to test real quick because i'm not i'm curious if it handles it i assume it must does it still generate the same property name even if i underscore my field oh it does [Music] it handles the default naming schemes that everyone cares about huzzah okay one more test one more test just just because i want to try it if i do this does it still generate correctly nah it works i love it love it love it love it love it love it okay but we can actually go even simpler than this because this fits on my screen even with my zoomed in ridiculous font size this still fits but let's go easier so if we come back here i'm going to scroll back up you'll note we had to write a bunch of code for our relay commands or the command in general and in reality most of the time we don't we don't care to do all this stuff like what i really want to write is this method all of this other stuff is boilerplate so let's come over here right so you'll note here here this has relay command greet user command so that naming scheme that i had mentioned where i like to name things with the command suffix and then my my thing tends to drop it but add the word on if i'm willing to give up the word on which i i think i'm okay i i'm going to do this and i slap this little guy on i what we can do here is we can go and you'll note i don't need any of this stuff anymore and if i and if i look here on this i've got a click command so if i just write a function and i slap the uh the relay command attribute on top of it it will go through and build this up for me this is cool this is very cool so let's just confirm that it works uh there were builders of course there are builders i left that thing sitting there let's try again we can come over here and yeah now the one thing i don't know about oh wow it has uh i am curious i am curious if i can get it to generate something with the can method on it i kind of want to jump because those docks are big and i'm not confident i'm not missing something we'll generate both an uh uh let's see let's see task method method yeah we'll get to async in a minute that one's cool uh i really was hoping this thing would do a um i don't know if this thing supports doing the other case where i really wanted to have a can method too just really hoping it did but maybe maybe we'll check i i didn't read the docs close enough uh additionally i can execute method it can also be specified it's oh oh yes [Music] okay this is this is too slick so once again uh one read the docs because apparently read the docs are cool uh this is just showing you how to create a command that looks like typing that looks source generators relay command attribute this is what we want create user command async we'll do async in a minute i want can oh so i literally just do that oh that's out well i didn't even think about looking at properties on the thing let's see what's on there oh oh oh no include cancel command oh oh you are uh don't redox you go to stackoverflow oh yes that is that is sadly true so let's put our can click back let's see name of can click and now we should be back to feature parody on where we were a moment ago but now when i do this guy click and it turns it off which is pretty cool now the other thing that gets really cool is let's imagine that i want to do an asynchronous method and i and i get i get all i get all crazy right and we say okay we want to assign it to robert but we're not real confident that we want to assign it so we're going to wait you know a second before we actually we actually do that because you know i'm not actually confident you'll know what i had to do i changed my method to async and i click and then it changed that's that's pretty cool in my opinion that is very cool and you'll note it also supports uh real quick go over the uh underscore ah so c sharp eight i think added the ability to have uh separators inside of numerix as long as you like underscores you can use any character as long as it's an underscore these uh all the underscore does inside of a uh numeric literal is provide a separator it has zero semantic meaning so it just gets dropped but it is you can actually and you could you could do garbage like this those are all equal to one 1000 but yeah so you shouldn't use them to add confusion i generally like to use them just to group stuff and you can arbitrarily group them this is most helpful if you're doing like binary numbers because oftentimes you'll want them in groups of four or eight or whatever maybe hexadecimal where you want to group and again some power of two to four or whatever so oftentimes they'll get used in that way in order to show them off but good call out robert so for people who haven't see them that's literally all they are underscores in the middle of a numeric have no effect on the generated code and are there simply to make code more readable so x groups binary groups yeah yeah very useful for that i tend to use it anytime i get over a thousand um just as my thousands separator just for clarity because i've started to learn even for things like like it gets i see even at 10 000 i have to stare at that for a minute just to make sure i've got the right number of digits like my eyes aren't great i tend to see that many zeros and things just kind of blur together so just for what it's worth so the other thing these things have cancellation token so we can actually get even cooler uh and if you spell cancellation token correctly it'll even find the name for you or get close enough and i believe on this one let me double check this guy let's go back up to the asynchronous bit uh so as that will be propagated to enable cancellation so you can actually set something up like this as well now it's worth noting if you take in a cancellation token you probably want to trap the operation canceled exception most things especially in the tpl when that token gets canceled or if that token gets cancelled um most of the time those will propagate up as operation canceled exception so you oftentimes at the top level command will want to trap this so if you make an asynchronous command that takes a token you probably should trap it the other thing is you want to if you do take in a token you want to actually flow that token into derived things that have it so let's actually make this bigger five and sometimes i'll actually switch this over there's an overload that takes a time span and it's a lot nicer so you know that thing flows in there and then after some time you'll also note that they have taken care of handling the case where oh it's now disabled now um i'm gonna actually turn this bit off and i think what we're gonna do is we're gonna plus equal a robber onto the end of all of these that where we're always changing but we're always going to so you know on the asynchronous bit because i think on the stream where i did tpl and wpf before there was a lot of questions that came up around well what happens if you double tap the button and all that kind of stuff you'll note it handles it for you and you'll also note that unlike a lot of the the relay command stuff where before we were using async void because command handlers are technically top level event handlers or functionally that with this we don't have to do that anymore we can write async methods like real people like real c sharp developers huzzah again more just icing on the cake of mwah it's just more more better more better more better um and if we look here i believe they had asynchronous commands uh enabling the disabling commands we looked about we already showed that um and then this guy here so that comment about the duplicate ones allow concurrent execution so if we go back here this guy here should have allow concurrent executions true right so by default it doesn't let you go clicky clicky and most of the time when you have a command you don't want concurrent executions rarely do you want that to be a thing there's i think only two apps i can think of or two instances i can think of where i've generally wanted all of the clicks and i didn't do something inside the handle or to like either disable the command or debounce it or something right rarely do i want it but i could go pop up and you'll note as soon as the first one goes in we get canceled because maybe we want it and again we should have probably trapped the operation canceled because now we're probably going to die yeah now we just crash and die which isn't great so if you write an asynchronous one trap that cancellation one yeah async exceptions await and rethrow default um oh interesting so if a command is configured to flow exceptions to the task scheduler uh but instead we'll both become available through da that's pretty cool so if you want to actually flow the exceptions up like for example if you've got some logging library that's looking for like these unobserved exceptions for logging purposes or similar that might be a use case where you might want to let those things flow through i don't think i would i would probably not turn this on by default probably because you'll note here this thing is flowing all exceptions to it not just cancellation like i kind of wish there was one that says don't do that so and you'll note here it's yeah this is this is even another cool one right so for example perhaps you have one button that kicks off like a download and you you want to then so you say you know what while the download is going i want to have a button that has a that allows for canceling it so here we're gonna do this try let's actually let's let's actually do some implementation right so pretend like this delay is you know do long download uh catch uh operation canceled exception so i will call out you'll note that the exception that was thrown on me a little bit earlier was task cancelled exception operation canceled exception is the base class of that and is generally what you would catch so first nay plus equals uh xx we'll just do we'll just do space x base when there's a cancel okay and if we go here look i popped the window out not okay i do not like that okay so let's give you another row boom uh let's see cancel by mean cancel click command so you'll note i now have another property on here that's just straight up i can cancel how about a use case that just breaks the usage of this toolkit now that sounds just like me okay so if i go click me and i wait some number of seconds you'll know robert shows up and you'll know my buttons are automatically toggling states for me i've done nothing like i just bound to a command i didn't no thinking no thinking involved i look this that's what i wrote which is awesome i am now focused on just doing what i care about right you'll note this can click not being used not being used and if i click and then i cancel i get the x because what's ending up happening is this cancellation command will cancel off this token for me i wrote no code well i wrote very little code i wrote the code that's important the the what should the thingy do stuff and all that boilerplate is gone like i i absolutely love things to get rid of boilerplate and and make this easy on me like this is absolutely amazing i love this love this love this love this love this um one thing i will call out this a lot of their docs pages call out this sample app um and i am so the sample app in question is a uwp app and you can see some of this i was hoping for more like i don't know it like it's it's kind of cool but like yeah it's also uwp not wpf and i'm biased and all of that stuff so maybe at some point i should submit a pr and see if they want an mvvm sample using wpf because it's it's great to show off great absolutely amazing to show off um so for what it's worth and then naturally they have tons of unit tests okay another advanced use case that makes me happy um so you'll note here we derived from observable object and most of the time that's fine it's very common when building out wpf applications to have like a view model base or some sort of base class that you want your view models to derive right sorry but that may not always be the case like there's been a number of cases i've run into where it's like well i have to derive from this other like library's object but i really want to add some properties that are going to be bindable and i'd kind of like all the observable object goodness but i i can't use it as a base class and that's kind of obnoxious because at that point then what i'm doing is i'm deriving from some other object and then i have to go back to implementing i notify property change and all that and that's just yucky and that's just you wouldn't it be great if we didn't have to do that so if we come down door cancellation broadcast don't care ah you'll note if i come down here i've got an attribute called observable object so if i take that and slap it on here now you know once again still needs to be partial uh and still needs to have appropriate curly braces because those are a thing right you'll know i have no base class right if i look at my base object right the only members on my base type are from system.object there is nothing special on me at all but if i look at my current object i still have all of my magic like on property changing that method that used to exist on my base class has now magically appeared on my current class so rather than like it's awesome that they gave us an observable object base class that we could derive our view models from but now if we don't want to derive our view models from somebody else's object or we can't for whatever reason we we can we don't have to give up that functionality we can just slap it on right here and then rather than getting functionality through polymorphism by deriving from a type hey we'll just implement that type inside of your partial class we got you we got it not a big deal not a big deal we got you right so if we look at observable object generator this guy here because you'll know right about now main window view model i don't know how many partials i've generated there there's more than one partial for this guy there's a lot of partial side so you'll note it went through and it's like i i got you i'll generate i notify property changed property changing i'll go through and i'll generate all of the members that would have existed on observable object so like the uh on property changed the one that took in where is it uh let's see there's all the set property methods uh oh i guess it didn't need an on property changed oh there it is there it is there's the caller member name one with all of that stuff built in and away we go and it just gendered all for us and it works and we can append roberts to kevin's and we can cancel adding roberts because sometimes maybe one robert is enough who am i kidding we need at least two um and all of that from an attribute now they also have a couple other ones on here for um i notify property changed so if you just want the i notify property change bits added on to your class it's like i could i could implement i notified property change myself or i could have a source generator do it for me like i used to teach people how to implement i notify property change i don't think i'm going to anymore i think i'm going to tell them reference the library and just slap the attribute on your class and call it a day because you could do it maybe mess it up or source generator can do it right the first time i don't know about you see seems pretty good to me seems really good to be okay pub sub stuff okay so the the other thing that often crops up inside of mvvm libraries that that quickly comes about is figuring out how do i communicate between my view models so uh for example um it is very common to say well maybe i've got like a service like when when i when i say the user to my database i want to uh you know pop up a little notification thing or maybe when uh i receive a push notification i want to like increment an uh an indicator or something and the question comes okay i kind of have like the binding and commands to go between my view and my view model but what about like when view model a wants to talk to view model b do they need to have a reference to each other and and how do i get that communication to flow so built into the library and i think one of the things that blog post calls out is this library is set up very a la carte style take what you want use the bits that you want if you don't need it don't use it no arm no foul everyone's happy right you can take as much of this library as you want but the the easy way to go about doing this is with the um the i messenger messenger boom right this guy um and this guy here comes with all kinds of fun stuff for either registering for a message or sending a message receiving a message or unregistering from it and the idea here with messages is messages are sent and and typically keyed by type so for example if i wanted to send a say a user logged in message what i might do is a public record because i might use a record class uh user logged in and that might have a i don't know string username right so the message itself is generally keyed on type and then the the data inside of that class is the data that might go with it so on on one side i might messenger register for a user logged in i want to register myself for this message right and then you know somewhere else in the app uh somewhere else we might have enough messenger send new user logged in no uh i i don't know uh jared because that's another name that randomly came to my head right so in one in one location we register for the message in another location we send it and these two locations could be disparate off completely unrelated to each other as long as they're getting the same imessenger instance either from di or from one of the static properties i'll show you in a second your gold right uh weak events seem to be slower than normal events is it okay to build a large program on them yes ish um so they it is worth noting uh and they actually call it out here so the if you are on like mvvm light your overhead for those events is like 52 milliseconds every time you post one which is definitely slower because the the big difference here is when you post an event ver so a regular c sharp event is just what's uh called a multicast delegate effectively you can think of it as a list of delegates hence the multicast part and when that event is raised all of those delegates on the invocation list just get invoked and go big bing bing bing bing bing fires them all up and that's quick that that's literally jump to method invoke done whereas for this there's a lookup that has to happen because the messenger has to keep a mapping of message types to recipients and so rather than just like walking down a list it has to do a look up get a list and then go down it so there is a little bit of overhead with it and there are two uh two messengers built inside of the library the weak reference one and the strong reference one so you'll note with this new library if you're going with the weak reference one if you're coming from mvvm lite you'll know there's a significant difference between the old one and the new one we're that we're down to seven milliseconds so if you're building a large app on them i one you're gonna gain a performance thing straight up however if you are able to appropriately register and unregister it may be worth considering using the strong reference manager um because the strong reference manager is a bit faster so just just to be aware but if you have the strong reference manager as the name implies it's going to maintain a strong reference to everyone who registers and because these messengers are usually singleton effectively they could keep objects alive much longer than they should be so if you are able to appropriately unregister go ahead and use the strong reference manager if you are not able to appropriately unregister you probably want to consider the weak reference manager because there is a little bit of overhead with the weak references right because even in c sharp when you get a weak reference to something there's that is a live check that has to be done first because before it can invoke a weak reference it has to first resolve it and go is that are you still a thing or are you dead oh you're still alive okay now i invoke so one i would say update to this library um because you'll know the key thing here zero allocations in this latest version zero which is absolutely insane in my opinion absolutely insane this is incredibly cool um there's some there's some deep uh documentation in here um for getting access to this dependent handle and the the low-level work that went into making this thing possible so that that is definitely worth a read but zero allocation like profile most of your code and see how hard it is to get down to zero allocation that is impressive that is very very impressive and the zero allocation is largely how they're getting so much performance out of this because if there are no allocations the garbage collector doesn't need to run and the garbage collector slows everything down so but yes they did they they did uh publish all their benchmarks and this is the key part here of how much got allocated answer almost nothing yeah because you'll know the benchmark was four different messages a thousand times to a hundred recipients effectively trying to bloat this as much as possible and in my opinion that's that's pretty good that's that is really really good especially comparing against effectively a lot of the the other common ones the fact that the maui one is so far down here just makes me cry now we just adopt this library and stop doing whatever it is you're doing um okay but but this is once again typing and hard and the other thing i will call out is unlike mvvm light which let you get away with basically this exact signature this one here you'll note when you register it explicitly wants the the instance here to be an i recipient of the message type so in order for this to work this guy has to be an i recipient of user logged in and the i recipient interface has a method uh for receive that gets invoked when the message is received so remember this code is off somewhere else in our app when this thing calls send everyone who's registered for this method message has their receive message invoked where they get this same instance and this instance can carry along whatever data you want right you can allocate um a message that's tiny like this or you could have it be a big object or whatever whatever is relevant for your message and it flows through um but but because source generators are cool uh yeah so they they show doing all of this stuff um this guy here i believe oh was there not did i misunderstand i thought there was a source generator to make this even easier uh registers explicitly oh i must have missed it thought there was a oh observable recipient this is what i was looking at this guy here we go here and slap this guy on come over here and we go [Music] show me this one uh this guy down here oh this isn't oh i misunderstood what this guy was used for this guy is used for something slightly different i misunderstood the observable this is for broadcast ah ah i misunderstood okay i lied i thought they had a source generator for generating up the the the registrations of this but apparently not apparently not so what i tend to do inside of these guys though um and i think i showed this back on the talk that i did with let's go back uh if i look if i go here and look at uh what is it but this one here with the generic host for anybody who's interested ah listening to myself talk there's too much me um in this guy here i had shown off actually registering up the the di container with the generic host so these guys here uh nope that's not the what i wanted i wanted that so this guy here you'll know both of the messengers do have a default property that you can get access to and pull these things up and i think uh yeah inside of the observable object you do get this messenger property um that you are able to go and powwow with now i don't remember this guy i don't believe where does he get set i don't know if he gets set or if i'm required to set him i think i'm required to set him so we're gonna do that for the moment and i think if i recall correctly that guy's going to be null let me double check this yeah he's not so the way you end up actually getting this guy populated it's like this uh i'm gonna move this into a different method just to change it uh private void foo that sounds great food do your thing okay uh let's see this oh uh okay so the way you populate this it depends if you are deriving from observable object rather than using the attribute so if we do this we change this guy back to observable object boom right so we still have messenger and if we jump to it uh we'll we'll end up seeing uh let's turn you off too just to make sure that it goes away oh observable recipient there happy good because observable recipient derives from observable object okay so if you derive from observable recipient you will note that there is two uh protected constructors on the base class one that takes in an imessenger instance so if you're using di this is what you will get if you are not using di it will fall back to using the weak reference manager simply because this is the least likely one to hosh you you might take a small performance hit but if you don't unregister it doesn't hurt you right it it it'll still work then we'll go from four milliseconds to seven milliseconds we'll be three milliseconds slower we won't like ourselves as much but it will be a little bit uh nicer which means in our class what we probably want to do is this so if you're doing any sort of di you will want to make sure that you have a constructor that takes in the messenger and you explicitly pass it through if you are doing it with the attribute with this this ends up being a little bit easier because then rather than having a base class that you're playing with you still want a constructor that takes in the messenger but you want to uh what's your problem uh um but you then go through and assign it yourself right and set it up and if you want to fall back to say the weak reference manager default property that's fine but if you're using di i would suggest registering it up here now if you just going back a little bit to your question justin bieber about is it okay to build a large app on this and this and there you do not have to always just use the static ones so you can in in some slightly more advanced cases and i've done this a handful of times like if i have a like a parent object that contains a list of children thingies and i want those children to notify me of stuff um you can create up your own messenger instance that you passed all the children and then you've kind of isolated that message flow to it's not going to everybody i'm not going to get the dii messenger that's the the global level one for example i'm going to end up getting a almost like a scoped instance or similar of of what this of what this one is going to be so you can set it up that way such that you could do it you could also register it as scoped in your di container and fun things there but in the case where you've got like a parent with a bunch of children that might be a case where you might say you know what i'm going to use the assuming i can spell i'm going to create my own you know strong reference manager and just use that one for you know this small subset of my app because you know in this case if it's you know a parent object with a list of children i know when the children are going in and out of scope i know when they're being removed from the list i'll unregister them everything will be fine right in those cases it's like oh okay i've got a very predefined lifetime i know i'm gonna do i know what i'm doing i can clean all that stuff up so in those cases i think uh it's perfectly fine to do it but again i absolutely adore all of these source generators and these source generators are fast too so they are built i've done streams in the past about building source generators and i should do another one these are using the newer source generator apis called incremental source generators um so they they go fast they go as you're typing so you'll note in some of these cases i haven't even hit save and i've already got the source generated so one the code behind the generators that these guys have written is very efficient very performant for one so that's awesome as well um but then they're leveraging the the newer source generator api to be even more performant which is just it's cookies on top of frosting on top of mountain dew which just makes me so so so so happy um they do have some fancy collection bits and they're cool and very performant the only thing that's a little yuckier is they aren't um the so the way that they show them off is inside of a uwp app using uwp controls which is like great i'm i'm happy there there's slightly more performant collections to play with huzzah um yay like they're they're great but i don't see i will probably leverage some of these um for doing it because they've got this this this nice bit showing here which is great um specifically when doing grouped items but like i can count the number of times i've done grouping on my items on probably without taking my shoes off so it's useful not a lot uh let's see diagnostics with guard clauses great uh net six support for native uh ins which is cool i i completely approve see did i miss anything was there anything else that was really cool in here messenger view model composition with attributes which is awesome because now you can like derive from your database type or whatever you need to be um oh there is broadcast which which this is a feature that's both good and bad um in wpf you can make all the same beautiful animated controllers as uwp except for acrylic controllers yes ish so you could build a lot of controls in wpf there are there's a handful of things when it comes to being able to do some rendering and performance that the the winrt which is what uwp and uh win ui three are based on are just going to win at um because they get to take advantage of some extra performance bits that don't exist in wpf so functionally yes there's nothing stopping you from building like a contacts style control um like what they have here there's there's nothing stopping you from building this in wpf there's not necessarily a great um what is what is the word it starts with a c i'm blanking on the name it's gonna come to me later and i'll just shout it out randomly um this kind of like being able to zoom out on the groups and bounce between them that control there um there's not built-in controls for that kind of stuff which is the which is the other kind of yucky part whereas uwp that control comes in the box it's like dang nabit it'd be nice to have something but i also again i do group collections so little it's not that big of a deal but yes you could from a functional perspective you could absolutely build this wpf there's just some rendering performance stuff that you'll never be able to match them with but yeah functionally you can totally do it um broadcast broadcast broadcast that's what we're looking at so the one thing that is sometimes handy is and this is also a feature i don't use a lot because it kind of comes back to the question about is it good to have something uh warning you about it you can in the generated stuff um create uh this notify property change recipients this broadcast idea where it will automatically push out notifications when the property changes i have very seldom used this feature even inside of mvbm lite because it existed there as well and it was cool but oftentimes what i found is if you have code that's highly reliant on a particular property changing it's been rare to me that i've had something relying on a property change and it's usually the only time this has made sense to me is in that like uh parent with a list of children type situation where you know maybe i've got i'm building like on my budgeting application where i've got a a list of line items uh for a receipt and as the the the dollar amounts in each of those change i want to update a total in the parent right something to that effect so in those situations you know maybe i'm watching an amount property and i want those changes broadcast up to my parent that's one of the few times i have ever needed something like this so it's kind of rare to use but once again you slap an attribute on it it auto gens the code for you and everyone's happy um which is just absolutely amazing uh let's see cancellation support for commands all of that jazz observable properties commands i think we covered everything i think we covered i think this is everything in the toolkit so hopefully that was was helpful to people like i said my opinion this is this is easily going to be my new go-to um for all mvvm work wpf or otherwise um simply because of how awesome this is and the performance benchmarks of it are absolutely unreal um the specifically uh sergio this this guy in particular um if you want to follow him on twitter or similar he posts some amazing performance benchmarks of the the work that he's doing he it is it is impressive to me the the speed performance that he can squeeze out of some of this code so if you want some some interesting stuff you know what here i'll drop a link um come on lewd load github uh sergio yeah absolutely impressive developer amazing with some of the performance benchmarks okay i think with that i am probably going to cut out a little early we'll call this me being at 90 percent and the what we're gonna cut out ten percent early i think that's that's how i'm gonna that's how i'm gonna pitch it that way that way it flows nicely so with that thank you very much for everyone coming out hopefully that's uh like i said helpful to everyone we will be back again next week there's a small chance i may end up throwing a bonus stream in at some point there's a couple extra videos i might make so if you aren't tracking my youtube i've got a couple of videos that i think i may make off stream just because i want to script them a little more so if you're interested follow them there because those ones will end up getting posted to youtube which is more or less my archive for all videos so that i don't have to to track them but i will see everyone next week happy coding you
Info
Channel: Kevin Bost
Views: 34,213
Rating: undefined out of 5
Keywords: programming, C#, WPF
Id: uVIzK2snugk
Channel Id: undefined
Length: 106min 12sec (6372 seconds)
Published: Mon Aug 15 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.