C#/WPF - Material Design in XAML - Code reviews and examples

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everyone welcome back uh tonight we're going to dive into looking at an example application there was a uh follower who sent me a bunch of uh I don't want to say a bunch of apps sent me an app that he's been working on uh over on the Discord Channel and I looked at it and was like this is kind of cool and he gave permission for me to go through uh a bunch of issues that he was having on the stream and I figured why not this this is probably a perfect example I can come up with my know little samples of different WPF issues but sometimes when the rubber meets the road that's where things get interesting so we're going to take a look at that uh and then I've got a couple other things we'll see we'll see how long things take I have no idea okay first couple things one Microsoft ignite coming up next week I will be there in person so if you happen to be at Microsoft ignite uh feel free to stop by and say hi I should be on the fifth floor uh in the the experts exchange area I don't know what they're calling that whole area um but it will be in the developer uh section of that uh over near Ballroom 2 so if you are around for that great if not ignite is a Free Conference you can register online uh or if you would prefer actually hang oning boom right uh the other option netc is also coming up at exactly the same date because why not schedule multiple conferences over the exact same time frame because that's not going to cause any confusion whatsoever um but uh NETCOM is fully online it's slightly more developer targeted you can kind of look at the speaker lineup and kind of gather a little bit about you know what you might see for example Fowler is known for his ASP Network hanselman's I guess all over the place uh David and Maddie are both Maui uh Daniel Roth uh expect Blazer related content whatnot so there's a lot of cool stuff coming there is also some free digital swag because who doesn't like cool images and whatnot so uh if you are interested uh and want to focus a little more on the developer stuff check it out um I believe I thought I had read somewhere that recordings are available after the fact as well but I'm not seeing that here so take that with a grain of salt that may may not be true we're going to go with I hope it's true oftentimes they make this content U fairly easily accessible okay so tonight I got a couple WPF apps so I got to figure out which one I'm looking at real quick because I don't know which one I'm looking at I think I want to start here so these apps here and I'm just going to quickly pick on this so I can look at the folder what I have now perfect okay so this is the starting position this is this is how the app started I was was given two versions of this the starting and then what Alex got to um and then I've got a bulleted list of things to take a look at so for starters first thing I immediately notice it's using my WPF template which made me happy which made me happy um I did note that he built this cool little split view thing out which is kind of cool I've I've contemplated doing some stuff like this um and if we take a look just in case anybody else wants it uh he is very much leveraging the um the ma apps stuff so there is this uh hamburger menu control you can see there's a a header template there's some items there's some options so if this type of view is what you are looking for there is some some built-in support inside of ma apps and material design and Ma apps do play nicely with each other there's a linking package if you run into issues with it let me know it's often times a pain for me to test so occasionally that that poses some issues but you can get you can get this kind of behavior I've contemplated putting something like this into the material design project specifically just because this layout with material design is fairly common so it may be a control that makes its way into the library at some point in time goal again is not for the library to be a control Library as much as a theme library but often times to do a lot of the material designning stuff you need need some custom controls so we've got this we've got this uh calibration grid and you can see that what we have here is we've got this kind of some plus minus stuff I don't actually know what I'm looking at for what it's worth so if you're asking me what large filament and small filament is one is large one is small clearly uh and they are clearly in different grids um and there's a there's a little bit here we're getting away um I was going going to see if I can find a a sample because large and small are basically the same uh width of letters you can kind of see that there's a if we get real close and detailed they they are off by I think about half a pixel or one pixel shifted left but for practical purposes unless somebody's going to zoom in these lines kind of line up here so one of the things we're going to look at is how to actually do the alignment of these things so there's that there's it's in here great okay let's look at version two so Alexa commented that he watched my uh recent video where we dove into the data grid and figured hey the data grid looks kind of cool it kind of looks like what I'm building let's go ahead and try the data grid now I don't know if you noticed there is something going on here when I click on this it's a little slow to load it's not huge but it is enough to be noticeable and it's like huh that's that's kind of obnoxious um and then you can see here this is basically the same except for now we've got this data grid style thing going on um and there's a there's a little bit of stuff happening here and even things like this sorting is dog slow like really slow so we're going to look at fixing performance changing some of this up I don't know which version of this app we're going to work on trying to decide because I was told we could theoretically scrap all of this that we're going to do theing random orders okay here we go random order it is okay so grid calibration page not shockingly this is where the grid calibration stuff is now uh one of the things that is important to note when you see it the the issue that's going on here uh actually we won't spoil we won't spoil it too much so so basic user control there's a view model if we take a look at the view model we can see that right in the view models Constructor it's just iterating through um this enum functionally which is kind of a a an interesting way of going through and doing this so there's this big long en here I mean I personally don't like theore en but everybody gets to name their stuff how they want but we've got this en there's some description attributes set on the various en members and there's just a bunch of them like around 98 of them give or take a little bit and so this is liter literally just iterating through all of them now a slightly cleaner approach here would be uh en uh get values right and so you could come through and rather than doing this I equals all right so I would I would tend to do something a bit more akin to this so let's let's change this up uh our enum value in and then this becomes en value and then this becomes en value boom right and this should be a four each because that's how four eaches work so slight minor thing in my opinion because this this saves you on somebody you know accidentally putting something after the end or whatever right right enes are just named um numerics but it's also worth being aware that they can have weird things where if you like turn on flags or somebody somebody could arbitrarily set the first value in here rather than it's default to zero we could do you know 42 because that's a thing and then this becomes 43 and then somebody could reorder and it gets it gets weird doing the enum get values is a little easier because you get just the declared values because technically enum value of 50,000 is technically a valid value it's not a defined named value but it is a value and since these are just names over uh numerics you end up with something like that you'll also note that there's some some wackiness being done here with the tabs we're going to get to that in a minute so we can see here that if we uh that we're that we're loading all this up but our first thing is to try to address the performance problem so if we go through and do this seeing multiple curses is confusing me if we click on the second tab you'll note the load speed is near instantaneous okay near instantaneous that's our first clue so something it's so it's not the data Grid or anything else in here it's something about the rows of the data grid because as soon as we got rid of the initial set of items the performance drastically improves this is like binary search level debugging of just start cutting things out and see when it gets better and then slowly start putting things back okay so we know that the the load of the items is what's killing us so if we relaunch I'm going to close this version of the app so I don't get confused to which one I'm looking at so if we come over here and look at this again once again several several seconds worth of slowness we're going to open up Snoop and take a look so for those people unfamiliar with Snoop once you install it crosshairs next to the binoculars or your best friend drag it over anywhere on the app that you want to Snoop doesn't matter where and then the next thing you do is you put your cursor over the thing you want to inspect and the Magical keystroke is holding down control and shift and it will automatically drive your visual tree over here to the item underneath your cursor um and then the other big thing to be aware of is um these numbers just to the left these indicate your nesting levels so I'm 43 nesting levels deep so it can be just a quick and easy way to kind of line things up so for in our case we want to go up to 34 we can see there's a data grid row now here's the next thing that hopefully gets people's attention when I saw this my mind immediately jumped because I was like hang on hang on like I only have a math minor which means I can count on both hands without having to take my shoes off but just ballparking it there's a lot fewer rows displayed here than I see here I see a lot of rows I'm going to go with about one for each uh item now the reason this got my attention is because by default the data grid should have been using virtualization which means it shouldn't create any more rows than what it actually needs for display but for some reason here this thing is creating a lot of them and so it's like okay that's that's interesting the next thing to look at is you go over here and you take a look at uh when we click on data grid and you'll not the actual height 4200 interesting the other thing to be aware of and it's very difficult to see on Snoop but Snoop puts this little red rectangle around the item that you have selected so so you can see there's the top Edge there's the right Edge we go down to the bottom there's no line along the bottom so this data grid is being allowed to expand to insane Heights now if we go up a little bit because we can we can look at this guy's data grid okay let's keep going up hold on the thing right above it has a height of 649 and you can see that our little snoop red thing we now see the bottom so the data grid is being allowed to become significantly larger than the container that it's within and so when we look back over here what's actually happening is there's this extra scroll viewer and I'm pretty confident this was just an accidental ad going from the old to the new because if we look at the old one previously there was a scroll viewer with a grid and a stack pan them some stuff inside of here and so the stuff inside of here needed a scroll bar and then switched over to data grid datag grid internally contains a scroll viewer so for any control that can that internally contains a scroll viewer it is rare that you should ever need to wrap it in a scroll viewer rare not saying never but it's it's fairly unusual to need to do something like that because the idea is that in internally it should be doing its own scrolling and by taking it by taking that scrolling away from it it's unable to virtualized because it goes well I'm going to get as big as I want and the scroll viewer says I got a scroll bar you can have as much size as you want it's like yeah it's not quite what we want so fix number one grid Row one move it down on the data grid we're just going to Nuke the scroll viewer boom actually I'm going to format zaml oo that might be a little aggressive does this thing have my zaml Styler oh it [Music] does okay I just love it love it love it love it okay so we come over here we're going to fire this guy up again click on the second tab there's a slight delay there's still a slight delay it's not nearly as instantaneous because it still had to to render all of these things however it is significantly faster and with some of these things there's not necessarily going to be a great way to always get it um and I would probably have to go in and look at how this ma apps control is holding on to its content I suspect it's similar to a tab control where the content is um thrown away when the tab control switches and not cached so blessings and curses for it depends on what you want so that fixes at least problem one great okay next problem these little numeric up down controls so we're going to take a look at these so if we go ahead and look at grid voltages this guy here is a uh bo boom just right above uh this is a very simple view model derives from observable observable object it's got a string for the First Column it's got a an unsigned short for the second column uh now now there may be a question of why unsigned short is being used here uh this is context it's so a few things that are worth noting sometimes people get it in their heads that using a a 16bit integer is more efficient it's actually less efficient than using a 32-bit integer which sounds counterproductive but the the reason is in order to leverage a 16bit the registers actually down at your um CPU level are likely going to be bigger which means these things end up having to get padded to be used so leveraging something smaller than 32 may not actually be buying you anything now it's very possible that for domain purposes you you don't want something to be bigger than this that's a that's a reasonable explanation um another good time to use like a short or U short is some sort of interop okay those are good things but if you're using a u short simply to save on Space you're actually doing the opposite because it's now using more compute to be able to pad that value out so avoid using um like U short short bite site there's one that no one ever uses um unless unless there's a a domain reason to do so right so that's that's the explanation but what we've got here is we've got this grid value now I am going to go ahead and do a partial here and we're going to go uh on grid value changed yeah we'll do that that sounds great boom boom boom F9 breakpoint relaunch uh and I'm going to immediately turn off this break point because as you can see I'm coming through from right here where this is calling the Constructor The Constructor the Constructor setting the property and then we're hitting our changed thing that's wonderful I don't want to deal with that okay breakpoint back on go to data grid okay so here's the question I go clicky clicky clicky and it doesn't update does not update now what's going on here so uh step one we're going to once again use our lovely little friend Snoop and we're going to come over here and take a look at this guy and figure out what's going on if we dive in here so control shift and then I'm immediately looking for the numeric up down control uh remember that Snoop is going to drive you into the visual tree uh and controls have templates and so you will often times land on things inside of the controls template so you sometimes have to work your way up so step one we're going to check our data context so we can accurately see that our view model has a grid value of 10 not great um but if we look at the properties over here and we check I think it's called value we can see that the value of the control is 13 and it has a binding on it pointed to path grid value that doesn't seem right the control clearly has the value of 13 the data context has a value of 10 but this thing shows binding pointed right there right click delve binding okay when you in Snoop when you uh delve into the binding what that does is it allows you to look at the uh the properties of The Binding object uh directly so we can see this is in fact a two-way binding so it should go uh back and forth uh let's see is there was there anything else in here I wanted to show I think that was it I think that was it uh at least for the moment so if we come back over to our zaml we can take a look the the data grid column is not fancy this it is a template column so it's uh you manage it yourself there's just a cell template set on here and there's a range from 10 to 1500 great and we can see The Binding here so what's going on so the the first hint here is if I if I double click in here and get my cursor where I I've got uh the ability to type in here and then I click out oh I might is it going to make make me change it and then click out no do I not still have a break point do have a break point did this earlier now I'm confused uh four oh four is smaller than the than the minimum 22 well that's just that's just dumb it doesn't work okay well spoiler alert we're going to come in here and we're going to change this guy so uh normally when this problem crops up it's with a regular text box and people questioning hey why is the value not updating as it changes so the the trick here is on The Binding itself the the default Behavior Uh of a binding if you look at its update Source trigger you've got see if I can zoom oh I didn't get it hang on hang on hang on we can do it this way come on take me there take me here boom this enom here has a handful of values there is default property changed lost focus and explicit and in general if you have it set to default default is going to be lost Focus so the often times the the way you can force The Binding to trigger is you can go through you can put your focus directly inside of the text box and then hit tab or click off to move Focus somewhere else in order to get it to uh update The Binding effectively tell the control hey take your current value and send it back to my view model please update immediately and our case what we really want to do is trigger this thing to update every time the property changes so that when the user sitting there clicking the buttons it actually goes through so now if we launch oops left my breakpoint enabled some point I'm going to figure out how to pin these windows here so that they stop doing that okay break point back here uh let's see uh yeah grid calibration collapse and now if I click old value 10 new value 11 so simple fix but changing the update Source trigger now the reason it's set up like this is because in a lot of cases you could imagine like a textbox that has a large form field some people type really fast and though your um property should be fairly simple there is a cost every time that binding has to go and update the value on your view model so sometimes you would like it delayed a little bit and not until the user is done the other thing that so that which which is why it is set to Lost Focus because in general does it really need to be updated as the user's typing or does it need to be updated when the user's done and has moved on because often times you know they type something into the text box they click the save button at the bottom that's the point where you then want to make sure the values committed and as soon as they went to click on that button Focus was lost from the text box your view model was updated and then the save button gets clicked so it all kind of happens really quick but it only does it once which makes it a little better the other thing to be aware of especially if you're going to change update Source trigger to property changed there's another little attribute on here called delay and this is often times something that will get used in conjunction with this especially if it's a field where the user is likely to be making a lot of changes very rapidly if you set a delay on your binding it it um does what's called debouncing so rather than just uh uh pounding on your view model every time the the value changes it'll actually wait until the delay has elapsed without a change and then write it so especially if it's something where the user may be typing a bunch if you're seeing a performance hit especially after setting the update Source trigger consider setting a a small delay on there couple hundred milliseconds usually does it nice does it nice in this case there's not likely to be that many changes if the user's typing or whatnot a few extra updates Eh this doesn't seem like something that's uh that big of a deal so we're going to we'll go ahead and leave it like that for now but again update Source trigger on the binding makes the numeric up down behave the way we want and We're Off to the Races okay let me let me check my list let me check my list uh let's see okay so the next one uh uh displaying en descriptions okay so this is another good one here is right now every time we want to do this uh uh I expected it change when the text box was losing focus but it wasn't changing yeah and that was what I was seeing before and I might have to go actually look at the numeric up down to see why it's why it's changing this because in theory it should have uh passed all the way through but uh see if we can trace down this may be hard to look at in the decompiled source yeah yeah yeah yeah yeah go away um value change coer that's what I'm looking for binds 2A by default validate on update property changed I might need to look when I was playing with this earlier when I when I move this guy across what I was seeing happen is it would in fact update when I typed in here and then tabbed away it would not work when I typed and now I'm confused as to why that is of why it's not picking that up also Alex I think you said it was very late for you right now shouldn't you be asleep um I'm going to take a note on that and I may Circle back to D digging into that a little more I suspect it is related to how the numeric up down is working um it could also be it could also be the fact that it's inside of a data grid cell maybe not uh see in the future I'd like to get it rid of Ms and use entirely material design but I need an numeric down yeah there there is a pull request for a numeric up down control in in there and I it is on my list of 5.0 things to go and do so if we get far enough that was one of the followup items I was going to take a look at uh okay um so let's talk about the the display of these things cuz I think that was the next the the next big one and for that I think I'm actually going to jump back I don't know if it's easier to do in your old one or your your current one so there are a couple ways to go about doing this and we might even just abandon the data grid Al together no we'll put it let's let's do this let's do this we're going to do side by side comparison side by side comparison so we got a data grid here let's go ahead and do uh co-pilot no that's exact why would I duplicate it bad co-pilot uh let's go ahead and do a list box I think this might be an easier way of doing it okay so grid row two okay co-pilot now do your thing no you can't figure it out oh dear Heavens co-pilot that is possibly the worst way to implement that um no dear heavens no uh let's see item Source uh one second uh sorry when your boss is messaging you you should probably check it uh okay and then tell him he can wait till tomorrow there we go uh so we are going to do a list box uh item template okay now if we look at what this guy is doing the the idea here is we have these um pipes that are currently sitting in the content that I believe the intent is we'd like to separate these things out into slightly different things so something into the grid something into position center and they only really need to be text but we would like the text to line up nicely right we want the nice vertical vertical bits going through here so um what I am going to do is I'm going to come over here and I think what would be nice yeah we're going to do rather than rather than fixing it completely I'm going to I'm going to do a little uh string split game here uh public uh string uh let's see filament do that public string uh grid public [Music] string position come on co-pilot figure it out what's the next one not smart enough okay kind of hoping you'd figure it out uh oh I can't do position uh okay we're going to call this alignment I'm going to completely guess at what the this is supposed to be okay and then I would like to do uh you're getting that's pretty close co-pilot uh uh no you were doing so good split on pipes that's all I want uh and then there there there there thank you copilot see that much was useful why can't you always do that um and actually wh while we're in here we're going to show off one more thing so uh what we should probably do is we're going to do an if position is and then we're going to leverage something that doesn't get used a whole lot called list pattern matching this is something uh new or I should say was new last year so if you're already familiar with the curly brace for property pattern matching list pattern match behave very similar drop your curly braces put in square braces you're done uh we're going to go string uh filament string uh grid string uh oh you had it copilot I'm sorry I'm sorry for not trusting you finish it out for me okay copilot now implement the rest come on oh nope come on co-pilot there you are thank you good co-pilot the one advantage of this of this guy here uh is uh and I'm just gonna make the warning shut up real quick oh you'll do the first ones but not the last one jerk um is this is only going to match if the string split has a length of four so I expect it to have a length of four it should be fine um if it doesn't this pattern match won't work and then it's also matching into here the other thing the list pattern match does have is it does have this concept say we we didn't want to care about whether it was four or more you can actually slap in a little dot dot similar to the range syntax that you can use but it lets you say yeah I don't care about the rest four plus whatever um so we'll do that okay but all of this so that we can do a data template uh and then we're going to do a data type uh let's see think we can do local and then it was grid voltage boom okay now here here's the kicker is we are going to come in here and we're going to do a grid uh grid column definitions we're going to do a column definition uh uh let's see let's do shared size group name and this is this is this is going to be the the magical incantation here uh cuz what do we got we've got oh we've got filament grid alignment voltage so filament uh grid alignment voltage now these names are completely arbitrary the fact that I have made them resemble our properties grid example right I'm going to do this just to prove a point is what is important is that the name is consistent not that it matches anything else what we're going to end up setting up here is grids that actually know about each other and will size accordingly so especially when you want to get things lined up vertically across different areas grid shared size scope is the magical incantation that we're headed towards that will hopefully make life a little bit easier so uh text block text uh binding what what I'm confused uh oh dang it that's why that's why I forgot some like style target type the property is to find as a type versus data template where data type is defined as object so if you don't do an X type it won't what you're talking about okay there we go hey am I pointed at the right thing yeah oh I'm debugging that's that's probably not helping my case any uh why did you why did you pop out one of my least favorite features ever I want to increase the drag length for that pop out Visual Studio I would like that option please there we go okay uh and then I'm just going to be real explicit even though zero is the default and then we're going to do grid uh alignment and then whatever the last one was voltage boom and then we just change this to a one change this to a two change this to a three okay that goes there that goes there that goes there and then the last thing we need to do uh well I should say last thing the next thing we need to do with gets and this is going to this is going to this is going to behave weird but we're going to do it anyway there and then we have to say What range this scope is going to be so what's going to happen is we're going to have a list box and inside of each of the list items is going to be a grid each grid is going to have four columns what we would like to do is have each of those four columns all be the same width so if one of them's a bit longer than the others they all should increase to match that size because we're using the shared side scope it needs to know how far to look to figure out uh where where it should find other shared size Scopes so attached property is shared size scope true so generally you'll set this at a highish level and by highish I mean the thing that's going to contain all of the grids if we open this guy up hopefully this just works be really cool if I got this to work on my first try okay you there Sit Stay okay so that is sort of working uh it has left me with a a little bit with a little bit to be desired uh most notably any amount of margin we're going to just we're going to just put a little space between each of these because this is being hard to see uh margin actually you know what we're going to do something slightly different let's do a uh uh we could do a separator yeah let's just do a separator margin uh and then we're going to do uh separator uh let's see horizontal alignment right that'll work move you up grid column one just going to intentionally slap one on the end of each of these there uh let's see two you should be a zero that's why I'm confused and then we're going to go ahead and do [Music] uh I guess I I guess I'm going to end up having to separate these in all the cases so let's just do this'll do a left margin on each of these just to push them over boom boom okay if we look at it now a little better the margin got applied at least uh let's see uh one I don't see it but I don't I also don't trust hot reload to to be rendering it properly let's try this one more time still don't see it why do I not see my hey Snoop why don't I see my separator separator should have a default style okay so we come in here content grid separator uh width one actual height 11 uh let's see do you not have a background oh it's because it is behind or on top of this guy and it is hard to see um um because this okay so rather okay okay I'm going to just fix this right margin rather than left margin that way these things don't land on each other just zero that out makes it better why I still don't understand why you're not uh rendering the way I expect uh there is that separator width 10 show it to me maybe it's just me but that doesn't look like a width of 10 what am I missing here in the right column oh there we go oh it's because oh that's why um let's see uh what is the the stretch vertical yeah that's what I'm that's what I'm wanting and I don't recall the appropriate thingy on here if I remember right uh let's just open the material design real quick if I remember right the it's supposed to play nice based upon the alignment it's one of the few controls that changes up Its Behavior based upon alignment unless I'm unless I'm misremembering which happens every so often uh let's see here so I want to give me the separator style don't care no no no no no give me back what I was going for no no no let's see themes test don't don't care about [Music] Ms uh let's see care about UI tests it's not going to be in calendar don't care about research dictionary separator nope nope nope now we're getting closer now we're getting closer uh let's see separator there that's the style I want show it to me right well nope that ain't G to that ain't going to fly okay fine fine we'll do we'll do something more like this order there no uh let's see uh uh border thickness uh let's see left top uh right bottom there something like that and then we do something like uh border brush uh Dynamic resource uh material design uh what was the um just looked at it a second ago I would like that brush uh but that may or may not be what version of material design are we referencing that's a 5.01 uh let's see the old brush name was interial design separator something something something separator uh let's see M apps uh it's probably uh I don't care that much is the problem uh actually let's just do this finding uh text element Dot there complicated way of getting around it but you know what it'll work so uh something like that yeah huzz that was way too much work uh and then we aren't going to do the margin here I guess we will leave a little bit of margin here but we are going to do a bit of a uh margin of I don't know five zero there something like that that was that was harder than it should have been but we'll do that we do that and then format that thing for me please and then that hopefully looks a little nicer uh except for I stacked them all in the wrong column which doesn't work put them there put them there there now we got a little bit better separation uh let's see one two three and there is a we we do have this tab thing occurring between the this bit in voltage but that is an artifact there so uh so cleaner possible options here is simply going through and putting in a shared side scope now the one thing that doesn't work well with this and I was hoping to show an example of it but it may be hard see if I can collapse this up small enough for it then recreates it uh it's not doing what they're all too close to each other they're all too close to each other okay we're going to make we're going to go change one of these so that I can so I can prove a point uh okay so for example great just need one to be the the text is just too close in in size okay so for example I've made one insanely large as we scroll down through here you'll note all of a sudden it jumps and the reason it jumps is because of virtualization and you'll note now as I'm scrolling up it's no longer there and now it's back now if I just go down a little bit still there still there still there still there still there here in a minute we're going to jump again boom and slides over so this is one of the potential pitfalls of a shared size scope combining it with a control that virtualizes because in order for shared size scope to work it has to look at the grids look at the sizes of those columns and then figure out the appropriate sizing with uh virtualization what will happen is the list boox items will get removed which means those grids will no longer be there this list still contains the same item that item is still there but it is no longer in existence inside of here so that shared size scope is no longer being picked up and therefore it now changes the size so that is one of the pitfalls to be aware of now there's kind of some options as workarounds in this case it may not matter that much right that is so just straight up ignoring it may work especially if the the real data is going to be close in size to each of these things it may not even be noticeable um othert options you can turn off virtualization on your control that works as well um and then and then the problem just kind of disappears a little bit um as it were um the the other option is you can play around a bit with the um the sizing because these things are all set to Auto that's kind of why we're getting the behavior that we're seeing is these things are all just kind of shrinking uh to where they need to be the other thing that's not really obvious if you wanted to like align something right um actually let's do this in Snoop I'll show this off is these things are all sliding over so let me finish my other thought uh the other thing you can play around with is like rather than with auto you can play with minwidth Max width which kind of helps constrain things down a little bit again just keeps the jumping around a little uh you can also not use Auto that that's another option but star sizing will get similar problems because if a certain thing needs uh full sizing and the amount of full size is going to be a problem as soon as you have any of those Auto columns in the list it potentially becomes problematic um but so for example these ones here where we've got all this extra separation if we go ahead and look here on our list box item we can see that the list box item spans all the way from one side to the other aside from the fact that my big head is in the way um but if we go inside to our grid the one that actually contains our items you'll note that the grid itself is is rather small so the grid is just over on the left and if we realize oh well hang on I really want voltage right aligned right for example maybe I say okay alignment should really be star sized well I star size it and it doesn't move anywhere it's like well hang on shouldn't the grid be filling the whole Space well yes but the grid is filling all of the space that's it's been given the the other thing to be aware of is on things like list box list view Etc uh list box item container style one of the common things that you end up wanting to do here uh style target type list box item uh based on uh uh material design list box item we don't want to lose our styling oh my work co-pilot you are you are amazing you are okay you didn't close the tag you can write you write 95% of the line you just suck at the L uh let's see is that actually the right property or is it horizontal alignment I think it's horizontal alignment that I actually want I'm going to relaunch because I don't trust what whatever the heck it just did okay come across [Music] here uh let's see it still didn't uh size it across why is it not sizing properly uh let's see or horizontal alignment stretch horizontal alignment left uh let's see horizontal content alignment what did did copilot actually get it right and the hot reload just failed no which which what is the property here that I'm missing item contain container style data grid list box list box item container style show me hey no give me uh let's see this guy here is Set uh because what I really want to see happen oh hang on oh oh no he is set properly now it's now it should span yeah and if I come down here okay good okay so my grid is sizing across got it got it got it got it got it okay so my grid is now sizing properly because now my grid does actually span all the way across okay it's just that the uh shared size columns did not expand the way one would expect uh let's see with one star I would have expected you to pick up the remainder of the sizing am I just being stupid uh because position center should have been the alignment column am I missing something here what am I missing why are you not uh grid why are you not doing what I expect you to do uh CU I expect grid to why do you not get wider there oh and we've got it a blank one at the bottom oh that's interesting I never noticed that before the uh the subtle switch that I did to the end from the for Loop is actually now picking up a value that we didn't want that is a subtle bug with the for each option um I am mildly confused because before it was cutting itself off here um why is this grid [Music] not doing grid things uh let's see grid the shared size scope this thing has a lot at the end huh did I ohc okay sorry it was sizing that way there we go okay so one don't be an idiot okay okay turn that back on okay so the shared size scope is what is mucking with the star sizing uh hey I he welcome I don't know if 6: a.m. is a good time to be out of bed I would definitely prefer to be sleeping I am mildly interested in this shared size scope and why this guy ends up sizing smaller I'm gonna I'm sorry I I have to look this up now because uh let's see WPF grid is shared size scope let's go here this guy here is and I got a I got a fancy new button that lets me copy links it's awesome um let's see oh look at that columns and rows participating and share sizing do not respect star sizing in this scenario star sizing is treated is auto so I guess that sort of makes sense because you would if you wanted star sizing it doesn't really make sense for it to be a shared size scope so if you want to do this properly then you just set it that way and then push it across and then you actually get the right Behavior okay that that kind of makes sense because star sizing sort of implies that you're filling all of the space and now you get something that looks a little bit more like this now obviously this is still bouncing because the first one is way longer and then as soon as it falls off it drops okay back to the original question of if we have this sort of separation of items what is the what is a cleaner way to go through and separate them rather than trying to manipulate the data and using tabs and pipes and that kind of thing data grid the other way of going about doing this is to um just simply create multiple columns so I think separating this apart so that like something like this I don't know I don't think I would try to basically embed all of this content in the description attribute personally if I was setting this thing up um I would probably go through and if I was going to decorate the enum I would probably have separate attributes for each which does then mean declaring a bunch of attributes and that kind of thing um and going through and doing it now the other thing that you can do is you can skip this all together right like this is kind of interesting in in the way this is set up um because if I'm looking at this this underscore G1 is kind of grid one and I can kind of and I'm guessing GPC is position center like it doesn't position wobble left so the the other way you can almost go through and handle this is by breaking apart the enum and uh parsing it because I'm trying to see filament small filament large and all of this kind of starts to fall out now that assumes that you want to do that but let's assume for the moment that we do um and actually rather than doing this we're going to change this guy up here uh to be like this and then I would like to pass in the en into the Constructor instead NOP paste nope not what I told you to do boom there okay uh enum value and let's just do enum value. get description just so that we can maintain previous previous Behavior then this can just become position um but one of the things that we could look at doing uh so let's do public um uh en value come down here and we go en value gets enom value so one thing that I often prefer doing in my view models is have the view model surface up the data that the view needs not necessarily the exact display of that data and the the issue with these descriptions is this is surfacing up both the data and how it should be displayed versus just surfacing up the data itself one very simple option here here would be to go through and say you know what really all we want to do is surface up the enom and then we'll go ahead and parse parse this thing apart as we see fit right we here we parsed apart the string inside of this but another option is to say you know what rather than binding to filament what we could do is bind to enum value instead is clearly not showing up because probably because I'm debugging and would have to recompile um is we could bind to the enom value instead and then just value converter it so for example uh rather than doing the the filament property because filament is just parsing this guy here if we come over here and we do add new item uh let's see uh uh filament converter something something something something and then do the needful because bad I value converter um I think this project has Noble reference types turned on because it's using my template uh build props n enabled excellent so something to know about with WPF when you have nullability enabled the WPF libraries were never decorated for nullability so the three states not the Tu most people think that once you have knowability turned on everything's in one of two states you know knowable or not knowable there's a third state unknown um and in reality a much better way of decorating these is something like this now technically somebody could still shove a null through like the target type functionally in the framework that's not going to happen so unless somebody's using your converter outside of it it's unlikely to happen so if value is is insert en type here uh en value let's see uh uh enum uh get name enum value and then we're going oh actually we can we can just be even better just keep going uh uh is a new name and en name split on underscores uh is and this is where the this is where the pattern match comes discard character string uh filament uh dot dot dot yeah so just to reiterate this pattern this will uh so this one if the value is the enom type great get the name if that is nonnull because this is an empty property pattern match store it in enum name split enum name on underscores as long as that split results in an array where we're going to ignore the first item the second item we're going to store in the string filament and then we don't care about the rest some number of items down there eh whatever and then we are going to return turn uh filament switch if I learned how to spell switch and then the only values I saw in there were FL and Fs I think yeah so FL returns uh let's see large filament yeah boom and then FS small filament okay co-pilot finish the rest sure that'll work thank you you're great you're great co-pilot and then here we're just going to return null I guess I don't care so what we can do here is we can come back up to this option and we can do something like uh us the control resources element converter like that and then this is going to want local for the namespace come down here and then rather than doing all of that stuff we can go with converter static resource filament converter now the the subtle advantage of this is that now our view models can go back to being kind of dumb and you'll note the ideal situation is we can't tell the difference which it appears to be working uh method or name is not implemented oh I probably got in yeah the NB one so that is fun we're just going to return empty string we should probably limit out that last [Music] one and we go here here we go and now it no longer breaks huzzah uh and we're going to come back over here and I'm going to just filter uh let's do where X is X not equal to grid voltage not Ben I can only assume Latin because that that makes sense I don't know if it's intended to be Latin but that's what I read when I see NB those people who don't know Latin not is often used in legal speak means no well pay attention Etc so something something slightly akin to this so rather than I guess the big idea here is rather than having your view model surface up how the data should be displayed and this is a very subtle difference but having your view model surface up the data to be displayed and letting the view figure out how to display it now is that better is that easier I think that there's a big a big it depends inside of there but versus doing this tab alignment and uh pipes I I very much do like the idea of shared SI scoped uh grids to be able to go through and um lay those things out that that would be my Approach uh for data grid you could you probably don't want to do a shared scci scope with a data grid as much as just breaking it apart into multiple columns uh that would that would probably be my suggestion so you'd end up with something like uh uh data grid text column binding uh binding uh let's see what what were we doing uh filament was the first one so you end up with something like this and you could even do something like can uh user sort false if you wanted and and not even set a header like that is that is technically an option here and you can see right now this is where where the the small filament is is showing up because data grid is by definition already grid layout and there's no reason uh oh and if you and if you do a binding to a readon property in a data grid you should really really really uh mode one way uh Andor uh is read only right depend depending on how you want to go about doing this I I imagine based upon the fact that this is coming from the en description that the implicit nature of this is one way that the user not supposed to be editing it but who knows um May that could just be a default starting point right so now you now you end up with something something of this nature now some people may not like the way that it does individual self selection but you can um just like in the discussion on the previous stream of the data grid you can change your selection setup hide that whatever you need so that would be my go-to there okay one second let me check my checking things uh let's see options for how to display enom descriptions in the data grid um yes so I think this is kind of where I would would end up going um and then that also uh lines up nicely with um how to go through and lay things out the one other thing I will point out is sometimes uh if you don't like the selection the the material design Library does offer you the option for hiding the selection in your list box another common approach that people do is they put a scroll viewer around an items control the disadvantage with that approach is you lose virtualization so take into account whether you expect to have a huge number items or not sometimes you don't expect to have more than maybe a few dozen items and whatever e either one's perfectly fine if you're going to have 3,000 you might consider something that virtualizes it uh let's see Alex it's for uh number I come from embedded world I mostly program in C and sometimes we do slap the en of our en the oh NB for number uh that gives us the the C Advantage for Loops oh okay got it also the U short is is because of the embedded uh marshing to transform the U short of the array of btes to send serial to the MCU ah okay in that situation that is a an excellent time to go through and actually use a a u short now there may still be a question of whether you want it to be a u short at the view model layer or just at the model layer but that that can be a a later thing to figure out because sometimes you will change data types up at the especially in a WPF up up the UI layer um I built a a WPF app at one point in time that was interfacing with a bunch of stepper motors for an industrial printer and down when we actually got to doing like the uh the comport writing and serial stuff there was a lot of things that were uh very intentional about laying out the bites because things like Indian start to matter a lot um and so down at my model layer I definitely converted into various different types to lay things out um but often at the The View model layer um I would still go back to just like a regular int um because there was no there was no benefit there so but it depends a little bit on on what you're doing and it may be it may not be an optimization that is worth doing right away but it is worth noting that if you're using a u short higher up you're probably actually hurting uh yourself not helping yourself but again it sometimes it is worthwhile for um like validation so like if you if you buy a a textbox to a bite property and then you try to type in 40,000 it's not going to work because it can't send 40 like the type converter can't get 40,000 to fit into a bite so um occasionally that can be helpful too but often times I prefer to to do validation with like Max Min ranges rather than data types um okay cool sorry I want to go back to your message that you sent me before and see um got it okay so the other question then here was around the the uh collection in the view model so down here right now this is an observable collection um and the idea was in theory we could get this thing down to be really really small um if we wanted to we could get this thing down to actually just be something like uh public list of enom values uh and you can actually do this and then you can you can even get real crazy and just do uh new en uh well actually you can just do this I could I could type it again or I could just copy and paste right and if you got down to just this point here where where you know that this is the sum total of all your values this totally works um you what you will end up doing though is you'll end up going the the the value converter route because if this guy were to bind uh let's see here because this was enum values make that plural we come over here and change this guy's item source to en values um what ends up happening is this guy converts the other bindings are all going to fail but we're just going to ignore those for the moment is you can then get something like this that then ends up working so your your view model then ends up just straight up being a list of your enes just surfacing the data that's important so in this case I show me all the en values and it's not even all the Unum values it's all of them except the number so in that case it gets you really really close and if all you ever want is this set and this is the sum total of everything that needs to go in there this will work perfectly fine the big disadvantage here will be um it it looks like you want enum plus this this value to go along with it and so there there may still be some pun intended value in having this uh grid voltage uh view model as an object but it ends up really just being a a holder for an enum Plus value you end up dropping position you this thing can be readon because if you're only ever going to change a property in the Constructor you don't need to take the additional hit of making it observable it can just be a readon property same with the collection down here if you never plan to add or remove items from this list it can just be a regular list the moment you want to do any sort of list manipulation you probably want it to be an observable collection now you technically can get away with um wa mutating this list and that's then just raising property change so for example down here you could do uh what is it uh base is it raise set oh on property changed so you can do something like this and you know uh so change the items in enom values so you can you can mutate the list raise property changed which tells the um the the WPF indan hey new new value here go through and change it the there's a couple weird gotas with this though so for example if all you do is like uh I guess let's do well actually let's do do this uh uh I don't know en values how about remove at and we're going to remove it zero and for in I equal to Zer I less than I can't type I less than 20 i++ right we're just going to we're just going to Nuke out the top 20 items okay so we come here we come here so we've got a list it's not easy to see because we have a bunch of small filament ones we're going to see how often so if I do uh receive data receive data receive data right I've now removed all the elements but we never saw the the list update secretly what ends up happening even though you raise property change The Binding engine behind the hood will be watching this to know hang on hang on this is still the same instance I'm good I've got the same instance it's like well yeah but you didn't update the collection so if you do end up go owing something like this you actually end up needing to do something like enum values gets new uh enum values functionally clone it uh let's see set and now if we do this and then and you can watch the little scroll by there boop boop yeah we end up deleting stuff off and now we're back into a a functional state so if you do go around the the route of manually raising property changed you have to watch out for the the subtle cases where things are equal but different because just raising property changed doesn't actually mean go and update it means go and check if you need to update which is why we we try to avoid raising property change till we need it so you can kind of get away with this approach but at a certain point the question becomes why when you could just make it an observable collection it's much simpler to it's much simpler to work with so um so if you wanted to get away with it um but you lose like this grid value thing and I suspect you actually probably want to keep that floating around otherwise what would this um numeric up down go with so we can actually come over here and oh I guess I I would have to bind it to the other collection so uh there uh let's see I think I have hit most of these Alex if you're still there is there anything else you were hoping for me to to cover on this one I'm just reading through the the chat and Discord really quick to see if there's anything else that I've missed my mouse is not doing what I want it to do um because I thought it would yeah I think I think that may cover the stuff I was looking for I think so no problem and thank you for uh the opportunity to being able to review uh an actual app So for anybody else watching this video or the recording later if you've got something and you would like a code review on it uh I can't always guarantee how quick I will get to things but I do I do very much enjoy doing code reviews and looking at actual apps because that's where that's where the real coding actually happens rather than in my own contrived examples because real apps have real problem problems and real constraints and real things and the problems are much more interesting okay so I'm going to close that I'm going to close that okay so there was one other thing there was one other thing that came out of the uh close this that came out of the drawer host discussion from the other the other stream and I want to do something here so MK dur uh let's see drawer navigation see door navigation uh net new you know you've used your template too much when it automatically fills it in for you um o let's grab the new one there's a new version of my template so uh and I will demonstrate what it does here in just just a moment uh RM star yes did you kill it all thanks uh let's see now build me a pseudo make me a an app okay so the one thing I did go and fix in the template was something that I had come across in a stream a little while back I'll just highlight that real quick and then we'll go into the actual drawer stuff so inside of your for uh app. zaml CS uh if you've been paying close attention um I changed up the way um the main method is being invoked um specifically so that the generic host has an opportunity call stop a sync this is important if you end up with something like a hosted service where you need to make sure you do Cleanup in it you will note I have done something potentially horrendous here uh however if you create an async main method this is the code that gets generated for you behind the scenes so the deadlock case is not quite the same when you are at the top level event handler now you'll also note you have to decorate it with sta thread because if you try to use an async Main and you put this attribute on top of your async method it will not propagate to the actual main method the last thing and I didn't realize this until I came across it your main method doesn't have to be public I've always thought it had to be public turns out works just fine as a private main method who would have thought so uh all of this cleanup all to just call stop async like that is the literal sum total of this and then if you turn on analyzers you will get flagged for this but I decided I actually preferred having this in here and explicit and making people remove it if they crank their analyzer up configure a weight true is the default you should never need to explicitly specify it I felt like it was important here to make it obvious that I really really really want to be clear that this is expected to continue on in the same execution context that we came in on which is the the entry point I.E sta thread UI thread do the UI stuff on the UI thread so just just because so um that's the that's the big thing is just so that this um stop I think appropriately gets called okay so but if you want to update your template or your apps that's the that's the change um you can always grab in if if you're ever curious what the differences are on the template one commit any working changes to your your repo because I hoping everybody us the source control next update the template and then just run net new and do a-f on it um so that it uh forces overwrite and then just look at the diff um and then you'll be Off to the Races um okay so let's let's go here so the other thing that that came out of it was it from the drawer host the uh um the idea of wanting to build out something very similar to how the demo app works where you have a drawer on the left and not too unlike the last app that we looked at and there's a set of kind of navigation items available to you and you want to be able to click on one of those and have it um do the navigation now this was one of the things that I had contemplated wanting to build out as a way of showing off um my template to have some navigation models so I figured let's build that out but I'm going to fire the demo app up real quick and we will take a look at it uh cool stop stop stop stop stop stop stop stop stop stop why are we hitting break points go okay there we are okay so here this thing here click navigate here click navigate that's the sum total of what we're going for uh okay so that that's functionally what we kind of want to build out now the only thing that gets a little awkward is I don't know if everybody necessarily wants like the position of this hamburger menu and the interaction of this drawer host is a matter of I'm sure debate among people but I think a better thing to do so we're going to we're going to build something out that works and then go from there uh so let's see here let's do this and we are going to do a uh color Zone come on find it thank you great okay and then inside of here we will do a grid uh actually I guess we don't even need a grid we can just do a dock panel and then we we want to basically poach a bunch of stuff from the demo app I think I think may change my mind here in a minute but we want to build out this thing so there's our drawer host uh this is what I want I want you so I want a toggle button uh dock panel dock top no in this case I want you to dock left pretty please thanks and then this is got it so the so there's two um two toggle buttons there's the one that is here and there's the one that is here and they just interact with each other like that so uh and then uh we do need then a drawer host uh give me one party please and then we're going to put all of you guys inside of here because the other question is where does that go in relationship to the to a menu if you have a menu does the drawer go inside or outside the menu I think the drawer host actually goes over the menu I think we're going to do this I I and again this is the this is the part of debate where I could see people going I don't like that sure fine it's a template change it um I'm going to put you inside you're going to go over the top and actually I think what I might do is move the menu down grid Row one and move the color Zone up now strictly speaking you don't actually have to rearrange these controls but from a sanity standpoint the the order of your zaml determines things like Z order uh and will affect uh your tab index so lay out your zaml in the same manner and you will get a bunch of stuff for free okay that goes there that goes there that goes there I don't know why I left this row at the bottom and then never put anything in it I should delete that off the template or use it could use it for something um okay so there's that there's that we going to just burn that off since we aren't using it and then in our drawer host we would like to do left drawer content and then we are going to do do I guess we can do the dock panel I'm not used to doing this dock panel stuff it's very weird uh let's see last child Phil false and in this case we're going to grab another toggle button slap it up here um at some point we're going to have to pick one of these things to drive and I'm somewhat tempted uh let's see menu toggle button is checked um I'm I'm thinking what we're actually going to do is X name uh drawer host and we're going to do uh is left drawer open and go something more akin to that that way that lines up a little nicer and this goes here and let's see here uh hor horizontal alignment that one should be right you don't need a horizontal alignment because you're being docked left uh format thank you uh let's see and then down here we are going to do a list box because we're going to want to control the selection and let's just steal from our demo app because we can uh this is going to not be quite what we want but it'll get us close uh boom let's do this here here format okay uh let's see so a couple things we can clean up we can do that I don't really want to give it a name unless I have to I don't care about automation properties the item Source we're going to need to deal with that we're going to need to deal with um selection we're going to need to deal with we're just going to do that for now uh let's see and then having a minimal scroll bar style seems very reasonable and then we're going to have to set a data template here at some point but for now we don't need it okay so this gets us into here and now this is this is the F the first point of contention of how do we want to build out our navigation this is one of the areas where Maui applications actually are really cool uh um they're cool and horrible at the same time net Maui shell so one of the things that they give you is this concept of a an app shell and they uh they're trying to accomplish something slightly different than what I'm trying to accomplish here but the idea is you can lay out and get this kind of drawer host slid out pick on the thing trigger navigation and Off to the Races but they also allow you to set up kind of this top level thing because inside of your app one of the first decisions you will often make is how do you want to lay out the navigation because your app will probably have more than one view the user will probably need to navigate between them there may be dialogues there maybe you know popup controls or uh snack bars or that kind of thing that pull out but you can then take this shell declare your fly out items and then the important part here is these individual items contain the content template and they then just wire it up for you WPF there's no such fanciness here you have to end up building it yourself but it is kind of a nicity little thing um so for example inside of your shell if you put these little route things on here it'll go through and do it and for people who build Spa applications this should probably feel really familiar to you because you end up with this nice little uh route that looks just like a little URI thing that gets passed around and oh look we register these routes and everything just magically Works um again cool and terrifying and kind of yucky all at the same time um like I kind of get why what you're going for but like this is not as clean as what I would like in a lot of cases but you know what whatever because it gives you things like pop the stack with dot dot like that's that's pretty e like some things are stupidly easy stupidly easy and other things are slightly more complicated like oh I just want to pass one of my objects around yeah no you don't so things like that so good bad that's that's how Maui does it um okay let's take back to my drawer navigation so I think what we're going to do is probably create us up a new view model for um of sorts and this is where I'm I'm trying to decide how much how much do you build out uh let's see so public uh class uh how about navigation item yeah that sounds fine uh public string title uh uh public type uh I don't know content type you can kind of see that this is going to feel a little maues a little ma ask uh let's see and then this guy here we're going to do something like public uh list uh navigation items and I'm intentionally just doing this as a readon list because this is not something I anticipate changing during the life of the application right this is going to be something I set once I may change it but any changes to this are going to very much be um done only at a single point so we're going to do new uh and we'll do page one uh uh type of uh main window view model and for now we're going to come back and change this in a minute uh I've been using data templates in my app. zaml for the different views is this recommended um it's not it's not bad it's so there's definitely uh I I think it's going to come down to a little bit of of how you um lay it out and organize it so the only disadvantage of putting everything at the um application route is this resource dictionary has to be loaded before your app starts so the more you put in here the longer your launch time if you aren't running into issues with launch time or any of that stuff it works fine the other question about putting it here is a matter of organization and does it make sense from an organizational uh management standpoint it's probably fine oftentimes I like to break things into sub resource dictionaries and maybe reference them up here doesn't fix the load time problem but but it fixes the organization problem so it's uh is it recommended depends on your app and I'd say it's not bad as long as it's organized well and you aren't if you aren't running into issues of startup time being long um it's not that bad uh but what to do instead ah good question so the other way to go about doing it so one I I like organizing things into resource dictionaries um and usually organizing them into resource dictionaries based upon kind of vertical slices of my application so here in a moment we're about to have multiple Pages for kind of different views of our application often times different views will end up being vertical slices so when you start thinking about the navigation model of your application like if you imagine an app with three tabs each tab is potentially a nice vertical slice of functionality inside your application probably again depends on your app um but organize them into resource dictionaries there and then only bring those resource dictionaries in when you need them now it does get a little challenging because the um with what we're about to show there's going to be certain places where that may not work because at the end of the day you're looking for a data template resolution that functionally needs to be at the top level now ideally you can bring it down tighter but sometimes if you're doing like the the tab style navigation it's only going to be known at the main window okay go ahead and bring it in uh uh let's see uh bit late to the party uh with question as running to catch a train to work uh uh virtualization was the phrase used and there's two types of virtualization UI virtualization and data virtualization uh often in WPF we are talking about UI virtualization so the idea that it uh like a list box won't create more list box items than it needs or a data grid won't create more data grid rows than it needs for what's currently being displayed regardless of how big your backing collection is um there the the video recently I think it's two back one back um that dives into Data grid I talk about it a little bit um for most controls it is on by default but if we do uh uh virtualization this page here let me just make sure it is the thing here yes this one here oh I love my new copy button um this one goes into it in more detail it is slightly different depending on which control you're using um in general you can turn it on and not worry about it too much but there there are things to watch out for like uh earlier in this video we were talking about grid shared SI scope it can when you turn on virtualization it can cause some occasionally unintended or undesirable behavior when it's only creating enough um items it also is worth knowing about virtualization um I was doing some work uh uh on an app earlier today where it was using a list view um and the the code that I was replacing had previously assumed that it could iterate through all of the the list view items to find what it needed well the problem is is I had turned on virtualization which meant I couldn't iterate through the visual tree um uh in order to get it to set uh in order to get to work right uh so you have to set a mix height on the w Window Control to make virtualization work um is you have to make sure that your control isn't just uh exploding in size that was the problem uh at the beginning where the data grid was uh inside of a scroll viewer and the scroll viewer was letting the data grid get as big as it wanted um most of the time with WPF controls will default to a horizontal and vertical uh alignment of stretch which means they're only going to fill the space of their containing of uh the item that contains them so most of the time you don't necessarily need to set a Max height because they're going to stretch and fill you know maybe the main window if they're at the route um and the main window may change size but you're right if if it is allowed to scw uh to size to its content that will break you so things to watch out for is like uh grid row height Auto is is a great one that usually breaks it because now it gets too big um sometimes it gets obvious because when you add in a bunch of items into your control you expect to see a scroll bar and you don't get one it's like oh well why isn't it scrolling well it's because the thing's too big so it's uh because the the UI virtualization is really a feature of the scroll viewer that is contained within those controls because the scroll viewer knows how many items are within its view uh in its window versus how many there there are total so when items are cycling through as you scroll up and down um it's what's taking that item recycling it around and rehydrating it appropriately um if you want a deep dive into it the tree list view videos um that I did for the material design in zaml I spent a great deal of time uh fighting with the virtualization I think think it's probably you can skip videos one and two I think I think it starts with three I think might have to double check that but yes setting setting a Max height or setting a fixed height I think might be a better way of saying it um and not allowing it to size to its content okay uh we were going to do this two three and then we're going to do this we're going to do this we're going to do this and then we're going to come back over here we're going to go here here here that goes there and then now that we have a object to work with we can do this we can do uh navigation item boom that goes like that I don't know why we have that set and then this is going to be something like title I don't know if I like that margin but we're going to go with it for the moment seems a little big let's see what it looks like and this is one of those areas where I I've been contemplating maybe even doing a second WPF template that has like this full thing built out a little more okay looks a little awkward uh it's clearly not lined up correctly but uh at least the buttons work so the the toggle buttons do what I expect the the menu looks weird this header is off uh let's see mode uh primary light n primary mid do that maybe let's do primary light just so it's a little different from the button color we could go primary dark I don't know I'm going to spend all I'm going to spend all my time just figuring figing out what the appropriate thing is I don't know I kind of like the dark I don't know okay that goes there uh let's see so this one here this was dock panel left and it should have been top because that's inside of the drawer host that's dock panel left so let's check this there that gets me to there and this ends up this is kind of an awkward um an awkward margin here that I'm not real sure I like I'm somewhat tempted to just do this as four all the way around see what that looks like that feels nicer to me [Music] um and then I think what we might actually do is stack panel orientation hor oh look at that look at that co-pilot okay co-pilot you've earned your keep fine I'll keep using you but only because you've made it really awesome and I I love that public uh pack [Music] icon look at you copile look at you go pack icon want to right you want to write the code for me thanks okay so we're going to do we're going to put we're going to slap a couple icons in here uh pack icon there like a oh this is um not the right pack icon kind come on co-pilot you let me type the wrong thing how could you uh let's see I think we're going to do like a smiley uh and then because that's clearly what page one will will be is the smiley face uh page two should probably be like a pallet yeah that sounds great uh and then page three uh is clearly a Snowman O Snowflake and that's that's tempting no snowman snowman is definitely the right answer okay play with this for a moment and then I I think we're going to slap a little bit of margin or a Min width on this guy yeah that looks nice I think what I want to do is slap a Min width on this guy uh Min width of like 250 a little big let's go a little smaller what's 200 look like I like that better okay um yeah I and and maybe at some point we want to put something else on the top up there because this this kind of is a bit of a dead area not sure I like so much of a dead area but whatever uh let's see and then this I don't like that being nearly that high off that just left lots of dead space and honestly I think I might just get rid of this all together yeah there's already there's already enough there's already enough space around this thing with a 16 um let's bring you down a lot thinking four was too much there I I like the idea of eight shrink this guy up a little more get it a little tighter yeah that looks a little better yeah I like that better okay great something like that something like that something like that okay great great great great great Okay so we've got that we've got that we've got that uh let's move you to your own uh move to navigation item and then we're going to do something like uh uh let's see uh observable property uh private oh fine you want okay co-pilot I want to stop helping you co-pilot just do all the work just a freaking showoff co-pilot just a freaking showof did you actually get that right yeah you did you did you did you did you did okay and then I think what we're going to do here is inside the dock I'm going to do something like um text block let's see doc panel dock top and this may or may not line up nicely [Music] uh boy we might just do this as a grid I I'm just worried that it's going to allocate space and not Center um so horizontal alignment left uh and then we're going to go here horizontal alignment center uh let's see uh vertical alignment center and then I want to do style uh material design text let's do like headline three I guess and then text gets uh binding uh hey uh title like that because what I expect now is that when I click here page one page two page three okay that's a little big um five better okay so we'll do that and then the only other thing that I kind of want to happen is when an item is selected um from the list box kind of want this left drawer to close um is left dra open uh binding is left drawer open so navigation I think should close the drawer is going to be what I decree we're going to go with another absorbable property private po what I call that is left or open h I don't know if I should call it I guess I kind of have to call it something with drawer is navigation drawer open I don't like calling it left drawer because that really like what if I move the navigation to the right should this property have to change uh add the page icon to that oh that's a good idea thank you we will do that uh let's see boom do that and then if we come down here because I kind of want to put them together let's do uh stack panel orientation horizontal because I want I want this thing to actually be what is horizontally centered and so we'll move this guy up here and then we'll do a uh pack icon uh kind uh binding icon and so I yeah I know icon's not going to work right that's not going to work but watch watch this trick watch this trick data context finding boom yeah booah something like that and now when you we're going to have to we're going to have to fix a little bit of this uh let's see width I don't know 30 height 30 we're going to want this thing a little bigger and we're going to want to put a little bit of space on the right I don't know maybe 15 let's see how that looks so we're gon to have to we're have to deal with the unknown case that's okay okay so that that worked um um except for this guy really needs a vertical alignment so that he lines up nicely horizontal alignment is no longer relevant okay that's a little better the 15's probably a little big let's dial that down to like an eight it's not bad that's not bad but at least then the sum total of this w width is what gets centered cuz I don't want it to do like one and then the other that just feels weird okay that gets me to there okay so we've got this is navigation drawer open we are going to come over here and go with uh let's see uh partial on selected navigation changed I don't need the old value I want to just set is now ation drawer open no co-pilot I said the opposite how can you not interpret my intent bad Coop okay so we go here we go here there now now when we click it moves us around appropriately not bad not bad not bad okay so that gets us that gets us in there um I think the other thing we should probably do is um select a navigation item get navigation item Subzero is we should probably default oursel to a page because you really should never be empty that works okay that is a weird looking Snowman like just think about that normally people put like branches um let's see uh why not private field uppercase because this is the visual studio default and what most of the world is used to um okay but now the question comes of dealing with uh dealing with this content type because at the end of the day what we would like to do is swap out um the contents of these so let's do let's actually create up a uh a couple things and again my my mild preference here is to group things by vertical slices so we're going to do something like counter right so we will go through and we're going to add in a uh user control counter view come on thank you and then we're going to come over here and we're going to go with ADD class uh counter view model something like that do something like that and let's see that's going to go there that goes there yeah so we're going to migrate out some of the stuff that was previously in here before so we're going to do the the actual incrementer so this guy needs to become partial he needs to derive from observable object your problem uh yeah you don't see the command yet yeah I know you don't see the command calm we will get there get there there happier now uh should we be using sealed on view models um I don't think the answer is related to view models specifically I think the question can be more generally answered of should you seal your class there is a small performance benefit from having a sealed class because when you seal a CL well we'll back up when you invoke a method that is virtual um there is a a lookup that has to occur where it works up the object hierarchy figuring out what is the appropriate method to actually invoke when a class is sealed it means it can't be derived from and functionally puts an end to that chain so when doing the lookup it knows I can stop here I don't need to keep going so there is a mild amount of performance to be gained from sealing up a class um sometimes people seal classes because there is um some bit of functionality that they want to be able to assume and they don't want uh anything deriving from the class and being able to override some bit of behavior so there's occasionally a time there that one I think you have to be really careful of and really sure of your domain um in general though if you're doing app level development most of the time you know all your derived classes and so if you would like to seal the things up to gain that small performance bump it's not a bad idea um especially for things that are non-public that are internal in general you can seal them um without much risk because it's an internal class you should know all of the deriv classes um it does sealing everything as kind of like a default setting um does end up causing some amount of problems and risk because the um if you use any of the mocking Frameworks that rely on something like Castle Dynamic proxy for example mock mq um will do this where it automatically generates a derived class of something the moment you Market is sealed you will subtly change that behavior so if you if you use Mock and you use a concrete type um so that you can do things like do setups on uh virtual methods um what it does is it generates a derived class for you and then overrides all those virtual members so that you can do your setups and verifi and all that stuff on it which is great the moment you make it sealed it can't do that anymore so you do have to be mildly cautious when I say you should know all your der classes consider your testing Frameworks as well and if they might be dynamically creating it if you are a library developer um be cautious on sealing everything um zamaron did this in zamaron forms and it was the biggest annoyance um because everything was internal sealed and it was very difficult when you wanted to leverage things because the moment you you seal it your you're effectively telling uh everybody that you know every possible use case and that there isn't any that should derive from this class that may or may not be a good assumption like as a library developer it's kind of hard to justify and say yes I know that no one should be deriving from this like there will be no derive classes maybe like that it's I as somebody who has put out a bunch of different libraries I can assure you your users will find use cases for classes that you had no idea they were going to use them for it's kind of like when you build an app and your users do something random um when you build a library the people consume in the library will basically do the same thing it's great um so yeah so long answer to what was probably a simple question should we be using uh sealed on view models and the answer is probably it's not it's not a bad idea but it should be worth noting why you're doing it it's either to um potentially gain a small performance bump or because there is some functionality that you want to ensure is never overridden Okay small detour uh okay down to here I'm going to take this out I'm going to go here and I'm going to just whoop slap that in there and then I'm going to set up my design time data context uh let's see design instance type uh counter view model and at present it's design time creatable so we'll do that and then this should give me a nice uh let's see right so these tests are now broken add new folder counter and I think we can solve this test Problem by really just reaming this thing uh to be counter view model test because really that's what we're about to test instead so change change change uh change telecode you are weird okay because we just moved all the functionality so the test can move down there we can do we can do something more like that okay so there's that there's that there's that there's that great great great great great okay and that gets us into there that gets us into there let's get this into here okay now this is this is where things are going to take a wacky turn is when when an item is selected we we end up needing to go through and do something right uh with this type of layout our main window has more or less become that same app shell like what we looked at a second ago with Maui its purpose in life is to hold on to uh the individual navigation items and then render them appropriately we haven't actually gotten to the rendering appropriately part here let's do that uh content control uh let's see grid Row one is that right no two I've already forgotten what yeah two there we go okay so this is going to be the one that actually contains our content so the the naive approach here right is content binding uh selected navigation item cont content type boom uh this mildly works except for the fact that it's not actually resolving our view model so you can see it's just so let's let's first fix this up uh let's call this guy counter uh and then this is going to be counter view model and then this guy boom so something like that and people have built various Frameworks to go through and do this kind of stuff something like prism is a one of the first examples that comes to mind of something that has tried to put order around the lack of the fact that WPF lets you do whatever you want but unfortunately that also means that you you have to do whatever you want so uh okay but our our question then here is how do we want to go through and handle this there are a couple ways to go through and do it um and there's actually let me see if I can find it there's a really great really great sample for things that I I wanted to go through and show so one option is inside of the on navigation item change because we we have this new item here one of the things that we could do is we could create a new property and rather than binding our content control to selected navigation item we could actually bind it um to that new property and then in here you know create view model and then you know assign view model to new uh property and then that new property gets bound into the content control and then we go ahead and let the um or then we create data templates for all of our top level things and and map them through I assume this is kind of what you were um driving at earlier JC with how you would set Yours up is there's some sort of layout here that definitely works I'm trying to decide if I want to go that route or if I want to do something different so one one option that's available to me is something similar to what we did with main window view model is we have this option here right is this is um this is a nice setup but the reason this setup works is because the Constructor for this view is actually being resolved from our di container works great the the disadvantage here is it means that the DI container is what's creating all of these and there's no there's no good way to pass data around but that's probably okay probably okay it it makes it makes doing things like uh parent child relationships a a little more interesting but maybe maybe we'll start that route so yeah I'm because I I am wondering if the I am wondering if a better thing to do because we have to put something on this navigation item to know what the thing goes to zamar forms they they have this as basically a a relative URL and then that URL gets mapped to some other view somewhere else that's an option I don't know if I like that option but it's an option I I think what I like doing okay hear me out hear me out I think what I like doing is uh counter view counter view model I think I I think I like this option here I think is set this guy up where it's something more like this and then di resolve the view and bring that thing across which means that what I put on the navigation item is probably wrong for content type and now I'm trying to decide what's the proper way to set these things up like how do we want to set these things up a very interesting problem very interesting problem of how do we want to and this is why it's hard to do a generalized solution because this is like I could do view type here right this this is a thing that could happen the the problem is is then this means this is uh counter view whereas this approach is so there's the view model first and then there's the view appro view first approach right you can come at it from either side if you do the view model approach you end up needing data templates to do the resolution if you do the view first approach um you end up having to do something funky in your view and you all and it's also going to require a fun di trick here in a minute um but then you also have this issue of how does a view model communicate an item without tightly coupling itself to the view itself self I don't know the right answer um I don't know um uh I'm just going to do this because I don't know of a good one I don't know of a good a good other way to do this at the moment and so you know what we're going this route uh uh yeah do that and then I think this is where I got tripped up on before when we started doing this is trying to decide and build this out because I every app is a little different and does this work every everywhere this will fall apart if you want to have a hierarchial navigation structure this is also probably a a bad choice if you want a a stack right in our case we're just going to assume none of that's a thing okay so yeah but this is this is this is sample this is sample this is sample okay okay uh I'm also questioning if doing these things inside of if building this list up inside of uh main window is the best place to do this but you know what we're we are stuck here uh let's see is there a let's do a calculator icon we got a counter counting that's math calculators are math done right okay so our navigation item now contains an En we want to go with a view first approach and by we want to we are going to because reasons um the there was a thing here I was going to go see if I could find for because I think I think Nikolai had a really clever way around um that [Music] will [Music] uh yeah let's see here there was there is cuz there is this issue here those people who want to see it um but in my case we are probably going to leverage this guy Let's see we will we will see but I think this is where we may end up go going um and I think this initial issue here linkeds back um to a to a technique in here uh let's see will the navigation on it uh those also tabs with their own content so in this case I'm just doing top level because I personally like top level a little better um this guy [Music] here yeah so this guy gets built up um and then this I I wanted to steal want to steal nikolai's work here he used a source generator to do the work but what I was looking for is the sample app that's what I want I want the user control setup because this is the desire here this thing generates an overloaded Constructor that then invokes this one so this guy here ends up doing something along the lines of this and then we're going to go and [Music] grab uh let's see here I want this file it's not plagiarism if you steal from yourself [Music] uh and then this probably a bad name for it but whatever going with it for the moment and then fix the name space yeah okay so this does something horribly bad that we'll come back to in a minute um yeah yeah something horribly bad that we'll come back to in a minute but we need it to do the horribly bad thing because it's important uh and we're going to do that guy there inside of our app do zaml and there okay that works now we're wired up and now we can come over here and we can do something like di uh get service uh and do this this I almost want to have a get required service um we're going to do that just so that I can have it get required service and we're going to make you be non-nullable and we are literally just going to do uh get service of t uh uh throw new invalid operation exception uh could not uh resolve Service uh let's see type of T full name boom good enough okay simple easy mode and then I don't think I need that anymore we should probably do something because we've also bro now broken the designer by doing this but you know what yeah we won't stress too much about that for the moment okay now last thing we need to do is when navigation changes we need to go through and actually create the appropriate View and I think for that we are going to do uh I think we'll just do a value converter I think uh uh uh let's see resolve navigation resolve navigation item converter that's a very long name we're going to go through and do it uh new item resolve navigation item converter boom fix this fix this fix this clean that up Implement that clean up the nullability on these because WPF is not decorated that would be the one of the coolest things if somebody wanted to invest a ridiculous number of hours uh okay so if value is navigation item uh nav item see otherwise we're just going to return null because we don't care at that point uh let's see return uh let's see navigation oh actually what I really want is location property uh and location it uh not navigation location unknown yeah uh now have item well I don't know if I actually want this here cuz I think I actually want it to fall inside of I think I actually wanted to fall into here and do something more like okay copilot you want to impress me finish the statement go no you're wrong see co-pilot you're not good enough yet you do it now no you need help uh get required service and this because at some point we're going to have to map do a mapping between one of these and another so counter View uh let's see and then I because I think I actually want to come come into here of dealing with this yeah something something about like that and then there is definitely like some people would like to put all of their um um value converters up at the top I really don't like that once again same same issue is it it has to load them all and do you really want them at the rout um what is your problem some custom elements have not yet been built yeah we'll compile them there you happier now there you go thank you uh let's see that resolves that resolves that's resol let's see if it even works so works right now is we launch could not result perfect so it doesn't work because we didn't actually resolve the counter or we didn't register the counter view or any of its related stuff in our register services so uh something like this private static uh void uh register uh counter I service collection uh add counter uh oh I can't do that in a so we'll just we'll just call it like this Services uh let's see add do we there's a question here about what should this be should it be a transient or should it be a Singleton huh let's do transient um uh counter view because this this is a good question uh of when we go to and from this page do we expect to maintain state or a clean state every time that's up to you uh let's see so add counter uh Services there now we should be able to di resolve these uh let's see public stud class application service extensions configure app Services yes and I I've often done that where I will go through and put these types of things into different areas I think the biggest thing for people is don't do all your di registration in one big block like that's ugly again I my my current personal preference is to vertically SL my application into like major feature areas and obviously there's going to be some cases where you've got something that's like a cross cutting like it's nice to draw my hands like this and make vertical lines but at some point there's usually something going horizontally it's rare that you can box your thing up perfectly like that it doesn't work that way in practice but most of the time it can um so I usually try to favor you know methods that have names around hey this is all the stuff to make the counter Feature work look it worked and then we can go page two and we can go back to counter and it reset and if we go oh you know what that's dumb I'd really like it if this was uh if it would maintain the state right right so we can come here launch this now if I go clicky clicky clicky right we click away click back right so without doing anything weird like we can start to control these things which is kind of cool it's kind of cool maybe a little cool kind of sort of and the big question here is does is something like this useful to people is this a the type of thing that you would want to see in a default template is this kind of layout because we can go through and build out more more user controls for page two and page three and have them be you know kind of kind of thing it is to me okay I I might go through and put something into my WPF demo app to do this this so and and I will say this I I don't know the right answer so I I will I will put this out there that way I do not know if it is better to be view model first or view first I have gone back and forth and I don't know that there is a one right answer in all cases so and this is this is probably not fully correct either there um to be friendlier to the um designer it's probably better to do a design time check in here too and shove a nll through and that kind of thing so there's there's something to be said about that there's also the question of should this be a required service should this just be get service this kind of pattern here for the DI is something that um on the link above where my my simply budget application I've commented to people before about my autod di library and how I've loved it and hated it all at the same time um because it does weird iel manipulation to basically give you um dependency injection by adding a n get package it's just magic occurs and things come in for free it does it's horribly abusive it's kind of cool but it's horribly abusive um I migrated simply budget away from it there's a couple thing a couple big reasons one is that there's a lot of tooling inside ofet right now that's designed around like optimizations and it makes the sweeping assumption that after it's compiled the dll nothing's going to muck with it which is usually a pretty safe assumption that after the compiler has you know compiled the code nothing comes in behind the compiler and goes well actually and changes it out from under it which is exactly what autod dii does it comes in right behind and blows it away um this is kind of a workaround to to give yourself that static resolution because at some point you have to get static resolution somewhere and there's actually you know we might be able to kill this sucker off well it's just so hard because there's certain places where like for example this value converter this value converter we could inject this differently like the only reason we need that di is to be able to do static calls like this we need a static call here and a static call here and technically this one can go away the designer gets really unhappy if you do this but functionally our app still works with without the default Constructor and the the key reason is because we're no longer trying to just drop the user control straight in our examle if we tried to just drop this user conol control straight into the zaml somewhere it would fail without the default Constructor which is why I say we probably want some sort of design time check because I I was just thinking that we could do something funky where technically main window and its Constructor in addition to taking in main window view model could take in heaven forbid I service provider or similar and then it would have to be responsible for creating up this value converter manually putting it into the resource dictionary and the code behind and y yada yada like that's a thing that can happen I don't know I this level of static I think is is acceptable um yeah and you'll know nothing's currently calling some of these things but yeah I think this is probably okay I think it's probably okay so I will consider going through and putting something like this into my template I'll have to figure out Beyond a counter what's a what's a reasonable page to do maybe we'll do like an about page or something that would make sense have something in there and again there's there's lots of questions about is this is this good right I I'm a little scared that people are going to take this and then run with it and go ah this is the way to do navigation in my app this is one way to do navigation in your app it's by no means the only way or necessarily the right way the other the other big option that I was considering was the uh is a layout that leverages the navigation rail because this is a quite a common pattern to see this kind of look along the kind of the left side of your application it's functionally a tabbed layout but along the side and so it's I'm a little torn on properly handling that and then you also get into Fun situations like for example we've technically broken this menu right I don't think this works anymore yeah because clear count is no long is expecting to find that command on on the um the main window view model and we've moved it and so then the question becomes well you probably want file exit to still exist here but probably only clear count when you were on page one that's a thing right so we could well let's let's just we can fix it and again I don't know if this is the right option but this is an option right so we will go here and we will go with um what's the easiest way to do this without triggering a binding air so that you can go through like so um oh I guess you don't even have direct access to it do you yeah you don't even have direct access to it that makes it awkward that makes it awkward because this is one of those situations where how do you go through and determine a what commands are available and especially if you're going to go if you're going to go with a view first this is one of the disadvantages of it if we went with a um view model first approach there would be a property here with a view model and we could then do bindings through it up here right we could do like you know selected view model Dot and even you know check its type pull out commands and have those types of things surface up with this you end up doing funky things with like attached properties to be able to surface information up and this is why it gets hard because the right answer depends on what type of app you want to do and what the interaction is that you want and this is where I struggle on trying to figure out what should be in my template versus is what should be left up to the author I think parts of this should probably be in there and maybe I should do a small sample of both or maybe I should have two different maybe that's what I should do maybe I should have both samples yeah maybe it maybe my template should take in a switch that's like you know dash dash navigation and you can either say view first view model first or none something like that that might be better and then people can kind of pick which way makes the most sense to them and run with it and it gives you enough to get up and running enough to show how each of those would [Music] work I kind of like that I kind of like that I might just ask this menu then or at least act this bit of the menu at least for the purposes of the sample yeah either way this gives this gives a little nice uh bit of information um and then for hopefully the uh the lovely comment that I got on YouTube about building out kind of drawer style navigation hopefully this gives some idea of what I was very poorly trying to describe so functionally the the Big Ideas here are you've got a list box in my case I put it inside the drawer um the drawer is open and closed with some toggle buttons because a toggle button is just a button with an is checked property and we just bound up the the toggle buttons is checked to the the drawer host is left drawer open we also bound his left drawer open to a property on our view model just so our view model can control it our list box has uh a set of items that that Define our top level navigation and then a selected item so that we can do work with it in the so that we can do work with it inside of our view model specifically the the work that we're wanting to the work that we're wanting to do is when it is uh assigned uh simply close the drawer and again this would be a point of deviation between where you would do either view model first or view first If This Were view model first there would be a DI resolution in here as well where it would say hey go get me the view model which is kind of the path that we had started down at the beginning till I changed my mind and went crazy mode um and in that approach you would end up with a bunch of data templates to to link things together uh versus The View approach where I ended up doing a an enum with a uh di resolution inside of a converter so this would be you know binding to the selected view model if we were going to go that route so something something in that vein and then you're off to the races uh uh am I approaching let's see 3363 let me pull it up one it sounds like you're fixing a bug which immediately makes me excited uh let's see 3363 okay when adding a button to the Dat Back style when the row is selected the selected row does not conform the [Music] generator uh which is a skeleton test okay so let's see here like that you built out this test let's see here so load user control with template [Music] buttons uh check the background color of Fus yes okay so in this case your user control is a data grid got stuck at this point okay uh let's see uh let's see data grid here has header visibility all item Source ID list great um view model list events great okay so header binding binding that's just going to straight up bind to the int and then there is so yeah so we expect a uh the First Column to just be the literal values 1 2 3 second column header button can sort cell style uh sell padding [Music] okay button template column here got it uh is the Button cell background that is the problem let's um give me one second you can go look at this and actually while we're doing this uh just going to kill that tag okay uh give me your fork and let's take a look this might be easier to do let's see what I need is one more remote uh nope remote and then I would like JL uh DG that one add and [Music] then okay and so I want to be let's just create a branch Branch nope uh creep Branch okay cracken stop it set local just put me there don't think too hard okay and then if I go here stop execution and then let's go close all the things that I've got way too much open and let's go down and take a look at this test uh data grids data grid tests and then let's do uh uh attach false just because I want to pause this guy and be able to play with the app so awesome work writing test by the way I very much approve and then I can show you how to reach back and grab the cells shouldn't be terribly difficult but I don't know if I've ever actually built one for doing that we can we can grab one though the worst case scenario you can grab um items with zaml test by index it's not a great solution but it's okay so that thing's busy hitting a break point uh let's grab Snoop real quick thanks come here yes the focus is the button interesting so that is I'm sorry I may be getting ahead of the game but uh chasing down where this guy's coming from uh okay so there's that I want to find where the heck that's coming from the the demo on that clone does the same ah perfect uh let's just Chase up the food chain think if I go here yeah so default style trigger so the behavior here is coming in from a style trigger on data grid 7 cell let's just jump to this guy and I am wondering how uh well let's or I get too carried away uh show me is there not a I'm guessing know the answer wow Visual Studio you want to you want to come back to me real quick thanks thank you um does that need a good sell cuz I'm wondering if this man end up not actually being a full bug and may be an artifact of the fact that that um when you don't set the base on you end up picking up the you end up picking up the uh the default uh WPF style for data grid cell yeah see that actually now handles it properly so I guess then the fixed easy yeah the yeah so this is um I jump back here real quick the this is actually something I ended up even putting in the wiki because there are are a uh th this basic premise of what ends up happening is you end up uh if you don't set a base Dawn you end up dropping the uh the material design styling and so you you'll pick up you'll pick up something the question is what and oftentimes is the default WPF one hey how's it going it's doing good I am doing good we were just reviewing an issue here so I guess then the question comes back to is there a bug here um and I don't know if there's I don't know if there's necessarily a bug here here now there may be a cuz that the the other thing is like this uh Setter is going to have um no effect without the Bas Dawn wow Visual Studio really okay we're kill you um because the the material design attached properties only a handful of them actually add behavior when you set them some people because with an attached property you can watch its property changed and and do work when people uh set the value to something but often times for most of the material design Library we don't do any work when the property changes it's literally just holding that data and so the the style or the template will watch that property and do stuff with it but the setting the property itself won't necessarily have an effect again there's a couple exceptions to that but most of the time that's the desired use case because it gives you a lot of uh control over what you want the thing to do when you put Behavior behind an attached property you have to start making assumptions and you can only get so far before your assumptions fall over so I think this end up may end up not being a bug simply with uh needing to set the base on so oh and that's what I was going to do I was going to check cuz you had set it here on the the demo app uh CU I assume if I look here yeah so same same issue in the the demo app is it just needs the based on and then it should work just work so I think that so I'll let I'll let you go back back and double check it uh JC but I think this one can probably be closed out because I think it's just a matter of adding the based on style which isn't something that we can necessarily always detect [Music] uh flag this on and then we can go from there but one first of all thank you for writing up those tests that that makes it significant easier to see and understand what's going on so very much appreciate that cool uh it is just about midnight for me and I have a uh a busy week followed by another busy week again if anybody's going to be around for Microsoft ignite did I close those pages already may have closed them I think I did if you're around for Microsoft ignite next week um come stop by and see me uh fifth floor expert Center uh I'll be around the developer tables at one of those um both days um or the other option if you're watching conferences and you're looking for something a little more developer focus.net comp is also next week November 14th through 16th uh both are free for online attendees sign up lots of cool content lots of cool announcements coming it'll be great uh yes also on that note no stream next week because I'm at the ignite conference and so it's already going to be a long day I'm not going to I'm not going to try to kill myself streaming after driving 5 and a half hours so with that said I will see everybody in two weeks as always happy Cody talk to you next time
Info
Channel: Kevin Bost
Views: 577
Rating: undefined out of 5
Keywords: programming, C#, WPF, XAML, material design
Id: QY3sfqaWiLs
Channel Id: undefined
Length: 176min 44sec (10604 seconds)
Published: Mon Nov 13 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.