C#/WPF - Multi-select TreeView

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everyone welcome back tonight I'm gonna dive back into material design xaml I apparently broke some stuff I had some notifications I need to clear out uh but more importantly uh in my day job I actually do build WPF apps what a shock um and one of those apps is actually leveraging the material design in xaml project and unfortunately we ran into an issue where we need a tree view with multi-select the built-in Tree View inside of WPF does not support multi-select out of the box which is very very annoying so I figured let's build it let's actually put it in the Box I think we'll put it in material design in xaml and this will be a good example of building out I won't say a custom control it's going to be a drive control and more importantly this is kind of a well-trotted path um you can do a quick Google search and I'll show them here in just a second of other people have built plenty of these in the past this is not a New Concept WPF is old which means if you think you've come up with something new you probably have it somebody else has probably done it before so when in doubt always look so let's let's take some looks uh actually this is we gotta we gotta go fix this I broke this so I might clean that up so customizing Tree View to add multi-select the key thing here with all of these samples of what people have built is there's one of two ways to go about doing this you can derive from the Tree View class itself and add it in because at the end of the day you need to keep track of control and shift and figure out how to do that selection and I think our end goal is going to be to make it kind of match the uh the Windows Explorer Behavior sorry one second I got things pinging me and making a mess uh okay so this one here person ended up doing a derived one you end up having to manage uh event handlers probably need to do some keyboard stuff as well um and then they went through and did all of the styling for it which I think we would have an advantage inside of the material design project because we've got most of this saw already we wouldn't have to do uh at least a lot of the the xaml side of the fence because hopefully we can plug in our existing one and just have it work um I yeah no and this is a way that some people have worked around it trying to um do some sort of is selectable and data binding into the back I don't like that approach um simply because I want this to be independent of my uh data bound side I want it to work whether somebody uses data binding or not so I'm going to kind of reject that option this one here was a little more uh interesting they went the they went the route of an attached property and attached properties people can kind of go one of two ways with them one is you treat them just as a property they're a data store you can put some stuff in but then you let like control templates and styles leverage them to add in the the extra functionality and behavior that you want however you can Leverage attach properties to add Behavior to things because attached properties have a an unchanged event effectively you're inside the center of a property and you can go through and Implement that in and that's ultimately what ends up happening here is registering up and saying okay if the value goes to true we're going to go ahead and add a Handler register up for the clicks and then go ahead and deal with the selection inside of here um this is an interesting idea to me because that the the advantage of an attached property is you don't have to deal with derived classes people can keep using a tree View as they want the disadvantage of attached properties is you can't override virtual members you basically are limited to the public API and I don't know if that's I don't know if that's a limitation that's actually going to bother us or not um the other fun thing is being able to get in and hijack like the container generator and put in your own in place is kind of a nice nice thing if you need to get all the way down to the tree view item to do something itself um yeah I'm trying to look and see how this goes we may play with the attached property approach the other one that's similar is you could leverage behaviors um as an option as well those require more than just vanilla WPF but if anybody's doing actual app development they usually have the behaviors and you get package pulled in uh let's see multi-select preview let's take a quick Gander of what this one is because I don't think we're gonna bring any of these things in wholesale but I am curious so this took the derived approach unselected dealing with the selection treeview got Focus yeah because I want this to be a fairly robust solution and I I feel like it's like multiple items continuously and this will be where things get interesting of um selecting items through let's see get all items blah blah blah not a big fan of that implementation this one here is interesting because this one has clearly seen um the light of day for a bit um somebody actually spent a decent amount of time building out a lot of this stuff um though the the repository has been archived as of May 2022. um curious which route this one went down because they they clearly did a lot of work on this as you can see they've implemented multiple things and so oh boy yeah this is this is this is jumping off the deep end in my opinion and this is probably more than we care about so this one here basically says we don't want the the TR the existing tree views Behavior we're going to re-implement that ourselves and so they've derived from items control rather than Tree View itself which I think is a bit much I I think that is a bit much yeah I don't think we're gonna jump I don't think we're gonna jump that deep that that sounds that sounds like too much so I think we're we're kind of in this vicinity here i s I do kind of like the idea of being able to do this attached property here and see how far we can get with that because this one here what is it doing is item selected this is one of the the awkward ones but I wonder why this one has to use the attached property and this is where I'm wondering if the attached properties might become a limiting factor is I want to be able to toggle the is selected property of the item itself and I'm wondering if we're going to get bit by doing it here because this is Tree View item and I'm wondering if the reason they used is item selected is because the built-in property would cause the other behavior and they don't want that and I'm not sure I wanna support both of those in here let's go down the derived class approach I think yeah let's do that because I think that gives us the greatest flexibility the other weird thing about attached properties and we see this in the material design project already is we get bit by the issues of um weird combinations because you can mix and match however you want uh actually before we dive in let's just go fix this real quick this is going to bother me I'm going to close a bunch of stuff down and I need this I need this I need nope not that don't rename the thing for me oh I need you come here okay so this guy here is I still I don't think did we add this guy in so this one here is just breaking likely due to an issue of one of these nuget package revs I want to make sure I'm not missing a nougat pack there's not a depend about PR City now yeah there is okay so these ones I should probably just need to rev all of those really quick and we'll be Off to the Races and then we'll go back and deal with the other stuff uh manage new package for a solution so dependabot does have uh grouped updates as a thing and I've been meaning to go and play with it and haven't done so yet so for now we are just going to um slap this in place and cool so that'll get us that that'll get us that we'll come here uh create branch new get update double check we do use centralized package management hoorah so we only have one file to review thank goodness getting new gets commit and then here because some people still miss this local branch has not been pushed click drag over Target Branch release Mouse push branch and start pull request yeah got got it gotta love me some get cracking okay uh because uh Panda bot uh hasn't been set up for a group grouping yet and that will fix the I should say that should fix the the icon update thing that keeps spamming my email every night when it fails okay back to here back to here Tree View time Tree View time okay so let's let's go in here let's go here let's go just I'm trying to think I'm really trying to decide if I want to run down that attached property route there's a lot of Precedence in this library for doing that there's not a there's a tree view assist and maybe we should look at that okay hang on hang on there's it really tempted really really tempted want to go back and look one more time at the implementation done up here to see if there's anything being done here that can't be done with an attached property uh uh so the word override will be the kicker preview Mouse down yeah that's probably a lot better to deal with set item selected get item is selected what it what is it is item selected I don't know why we have a dependency property for is item selected on a multi-select preview you want selected items yeah um oh is this a attack oh it's an attached property see this is what's what making me wonder why everyone's going down this route of an attached property to know if it's selected yeah we're gonna do a drive class I I don't understand why everybody's doing it and so we're going to go and we're gonna go learn me some reasons okay so uh new item and now the hardest part of the whole thing we would call it uh multi select preview yeah we'll go that we'll go there for now okay do that review oblique okay now where we get carried away at all at all we're gonna just get this thing working out of the box real quick uh okay so Tree View here we don't need any of this stuff don't need any of this stuff so we're just going to go straight to the defaults and we're going to come over here and we're gonna go Tree View we are going to do uh uh multi-select preview and this is going to end up needing to be a let's see where's m sorry I got a Band-Aid on my thumb so my my typing skill is going to be exceptionally bad tonight not just its usual level of bad uh let's see CLR come on oh uh XML namespace mdix equals come on CLR okay there we are uh that guy so then you become mdix that then we compile and make sure you build [Music] oh we should probably have set the autocomplete on that PR we'll rebase on it when it's done just to get those build warnings out of my hair okay that compiled hoorah let's go to the demo app we're gonna go to the tree views we're gonna slap together a quick example Joshua welcome we're just getting started the big debate derived class or attached property there's no good answer is the short version uh let's see let's fire up the demo app really quick because I'm curious to take a look at oh and we can leverage the new feature yeah we've got a new feature uh why does it yeah there uh uh trees is that what it's called trees now if I do this command line launching and then oh look at that it goes straight into the tree view okay so the idea being if I hold down control I want it to select um maybe we just copied the basic Tree View and put it over here and do that so let's take the basic Tree View which is this one here yeah copy this guy uh I actually copied the whole thing and then let's see so this is we want to be column two so I think we're gonna go uh let's see the text blocks are the ones that are sitting in uh the first one and so we are actually row two no Row one we want to be here we want to do this and we want to name you trees I think if we do trees three we're going to have conflicts but we're gonna we'll go and rev this trees three trees four because xaml display doesn't care what you make the keys they just have to be unique it's five I've actually contemplated going through and eliminating the need for this all together but haven't gotten around to it haven't gotten around to it okay so and then we're gonna do something like this this comes here so let's see do we bump the column we did not column zero one two right zero one two and then this is going to be uh it's gonna be similar to this except for it it will be a grid uh column two and then we'll do uh multi-select and then this will be our multi-select Tree View all the things and yeah okay let's make sure this this much should work and then we'll just implement it I mean that's all we have to do is just just implement it okay there there okay so that that appears to be working and if I look here I see it is showing me the multi-select review has that great great great that is what we want and something about like that okay now now we have to make it work why do we have this I don't understand why we have a text block with a single run in it just set the text property and then self closing so something special about okay whatever okay so let's come back over here and this is the part where I suspect we start to figure out why people have done it the the way that they have so we're gonna we're gonna briefly steal a little bit of code I think don't like that I don't like that these might be useful um I feel like I want selected items to be something bindable but I don't think that's what I want yeah this is weird why would you yeah so we're gonna go here we're gonna go here and we're gonna see why why is this thing so hard that people have bent over backwards trying to make this work uh let's see on key down I got focus on let's see expand subtree get container for item okay so all of those are fine selected item changed that feels pertinent items change don't care don't care I think that's going to be the key one to grab let's go here and go override on selected item change we're just gonna preemptively grab that because I think uh let's see e handled want to grab this this is this is a worthless thing just to keep it from collapsing on me get Tree View item clicked I don't like making this assumption on clicking the expander because let's let's compare what we're what we're going up against uh so for example if I do that that no that doesn't allow multi-select where do I have a good multi-select view need a good I need a good sample here one sec foreign I kind of sworn Windows Explorer allowed multi-select in his tree view but apparently it doesn't that's dumb okay well we won't be basing this on Windows Explorer then because that's uh no bueno okay so select item internal what did they do there uh let's see we're just gonna grab this really quick uh we have better ways of doing some of these things but we're going to bring this in just so that we've got an implementation to work with and then we'll change it up okay preview Mouse down we already had that one whack it that goes wait did I not copy this copy give me paste there we go okay so control shift pressed those are probably not bad utilities to bring in they're just convenience functions but I don't mind some convenience functions uh yeah we're going to expression body those guys because no reason not to okay and set item selected last item selected why we're gonna we're gonna grab these items real quick just last item selected used in shift I oh I see they're tracking their last one so that you can expand the selection oh actually I know test test Explorer you support multi-selection because I can do this and this yeah this is the behavior I want I want this Behavior or I can do this this this there we go there's what a multi-select preview looks like test Explorer thank you thank you Visual Studio this is what we'd like to build and the control click on the expander just invokes expansion not otherwise great thank you okay close that close that close that close that okay set item selected is the last thing that I didn't grab uh really oh set item selected is setting the attached property I don't like this we're going to bring it in and then we're going to delete it because I don't like relying on that uh let's see visual tree helper that's built in um we have a built-in thing for this already uh what did we call it is it just tree helper that's the find child I thought we had a find ancestor already in here uh uh maybe not okay so we're gonna do that pattern match that guy see you are knowable clearly item list let's see here I don't like VAR in this case it is clear uh this is clearly notable see that goes there that goes there we're gonna get rid of this I suspect we'll re-implement the bug but that's fine I don't like that as the way of detecting the expander because if it's re-templated you can't make ex you can't make assumptions on the UI elements of the template let me phrase you can't make assumptions on the UI element of the template unless you have a template part on your custom control so if I go there and that's what's bothering me is when this thing sets the set items selected why are we setting an attached property versus uh Tree View item like there's already an is selected like why are we not leveraging that I I have to believe there's there's something that this propagates to um just why I don't like I don't want people to have to think about a different is selected property that just seems bad it just seems really bad and I don't want to do that uh let's see so get rid of that Tree View item is selected through all right you co-pilot I appreciate your assistance most of the time sometimes I hate it uh uh okay that's a better we've got a lot of ads stuff in here that we might clean up okay so let's let's try this and see why is it that people use an attack and their own is selected property because I I have a hunch I know why foreign okay so that tells me that the reason people are doing this is because either the tree view or Tree View item is watching for that and mucking it up for us uh let's see set selected selected value blah blah blah uh tree update selected value prepare because I'm willing to bet that's the that's the Crux of the whole thing what do you derive from actually items control oh so you know what you know what we could do something really crazy oh dear Heavens no we couldn't I was gonna say we could just copy the code and bring it in but we really can't when they've got methods like this hanging out in there because that's uh it's never gonna work okay handle Mouse button down see but this these things are virtual like you can override the tree view item like this is where I'm this is where I'm really confused so is expanded changed great is selected property on selected on unselected these are both fine these are just routed events what this tells me is that this guy is watching for them and handling them we can test that theory because those are routed events and our good pal Snoop lets us look at and Snoop routed events let's let's test that theory real quick you go there you go there you go here I would like to watch events I would like to change tracked events I would like to go look at trees uh let's see selected unselected selected item change those are the events I care about if I click here okay selected item changed on multi-tree view okay and then unselected fires from the Tree View item selected item changed comes into here which kind of makes sense selected on Tree View item then raises but I'm not seeing the tree view or true view item handle it it's going unhandled that's the the green would indicate which element handled the event and no one's marking the event is handled so despite the them being there they aren't being and I'm wondering if this type of stuff here is why people have elected to roll one okay so that that explains why it's doing that is they want a different selection well I wonder how close we are and we are we are not that far off not that far off I know this is a bad idea but I'm kind of tempted to do it anyway I'm curious I want to see how close it is it if if I wanted to go down this path how bad is it how bad is it how close do we get because some of these things I think we can handle um some of these things we don't need to handle uh let's see they have a boxed Boolean um we we could just go false we don't need to worry about boxing at the moment control Trace logger we don't care about um keyboard navigation [Music] doesn't have the focus bits this is unhappy about what the uh uh nullability oh what you're unhappy about Cinder is active private property uh um yeah we're really close because none of this matters I do love how we've gone to all the effort of creating a bit enum to hold a single value so that we can like okay I get it guys I get it you were going for perf but we won't need that we won't need that we'll need that it might not be that bad it might not be that bad keyboard navigation [Music] get visual root the let's look at that foreign keyboard navigation uh get visual root this guy is hidden away from us but is there what exactly is he doing is he exposed to us via another method uh no [Music] no why are so many things hidden away from me when I want to touch them but do I care I don't know if I care that much so is keyboard Focus within we know we're in the false case for ourselves um selection should appear active comment out this whole thing for the moment because I don't know if we actually need it okay it's selective actor property key box booleans we're just gonna send the Boolean rather than deal with that and this is trying to set value for the selector is selection active property key um yeah we can go out that route and go around it uh let's see just gonna clean up some of the spelling while we're in here because it bothers me do that okay so some of this stuff is now going to start to show its age as this was written well before Noble reference types were a thing we can clean them all up as we go automation appear Tree View might have to do something funky um we're gonna just not deal with automation at the moment my apologies to every QA engineer who is freaking out right now handle scroll by Page what triggers this is this like a page down yeah age up page down navigate to start we're going to just do this for the moment and comment these out because clearly there's some navigation elements not being handled scroll host een go back press this handle scroll keys we're still in keyboard navigation take me back to Tree View not the win forms one the real one thank you uh let's see here and the scroll Keys handle scroll Keys scroll host uh that's freaking out because we have it handled probably go top top to bottom uh let's see bindable true these are should all be public attributes we are going to kill this off here in a moment because that's not going to be a real thing we're gonna have selected items it's the null ability as we go uh no we're not gonna do that not gonna do that selected value path binding expression um that's not going to be a thing because we're going to change up all of this selection so I don't really care selected item it's going to become selected items see here there thank you thank you AI overlords uh selected container uh this I don't care to fix because we're going to upend all of it so we're just going to comment out whatever we need to make it work uh this guy here we're going to just make sure he takes a nullable and then we're going to jump back same with this guy here make sure he takes a nullable jump back this guy here needs to be nullable this guy here needs to be nullable jump back that FanDuel handles all of those that becomes nullable okay so we're good to this point raise automation event we're going to just clear that up clear that up okay raise property changed event handler these are clearly nullable uh let's see is selection change active I heard Auto property because that's the easiest way through this uh update selected value I frankly don't care to deal with this so I'm just not going to because we're going to change it all uh prepare selected value path binding expression once again don't care and in fact it's now on referenced with my other comments so let's just kill it all completely handle selection and collapse preview item parent Tree View item oh you dirty dog you're telling me that these things know about their parent you just don't bother to expose it to us look at that parent items control so we could we could Implement that if we wanted um I'm Gonna Leave It commented for the moment um and then change selection click that we're going to fix the spelling mistakes and then [Music] I'm gonna clean this up do that do that do that okay and then this is technically nullable um fight collection change the Menards that's a real thing let's see selected item is definitely nullable which should be all the items Sub Zero we're gonna do that for the moment select a container is nullable so we want to make sure you get declared nullable jump back not supported exception uh uh yeah we're gonna do that for the moment see container gets declared nullable item probably ends up being nullable let's see so container here becomes doable item becomes nullable which propagates backwards to this item which means this needs to be declared Noble as well jump back and and in selected container parent preview you have knowledge of your parent Tree View as well look at that huh um uh we we might just go and Implement our own Drive class okay select a container that goes like that goes like that handle scrolling uh uh yeah we can't actually override that can we uh control handle scrolling checked it internal uh let's see the tree View that's weird that is weird uh I guess it's because internal would still be straight up internal kind of makes sense makes my head hurt don't really like it that much okay that gets me to there gets me to there gets me to there expand subtree needs to take an anole great going down Focus first item uh return false uh let's see false hey look we've seen these before our old Pals well this is a slightly different implementation rather than checking key down to checking the keyboard modifiers which I think is slightly more efficient if I uh remember correctly don't need the extra Prince that's no longer helpful scroll host I think we said we were going to do that uh W till uh greater than what the heck does that do what the heck does that do uh let's see true you uh yeah is this literally a double comparison okay we're gonna I'm not entirely clear what that does so I'm gonna assume that this is literally that uh uh okay let's see original focused element is unused excellent uh see item info info from container this is scroll by page which I think we're gonna just not deal with right now we're gonna go down here here okay gets me into there gets me over there let's be past that so scroll host is the last thing that's biting me let's go and take a look at that what's your implementation look like scroll host I'm the only one who missed it where is it lovely so you are internal and you are literally just walking up we have an item so so walk up the tree looking for a scroll viewer interesting this feels like something that you would actually do on the template for this um we're gonna do this we're gonna do this we're gonna do this done Okay so we're gonna rename this thing preview two just just to see right because this should get me uh let's see tribute review two should probably hunt type of tree view real quick just to make sure I didn't miss anything um yeah because we don't want it being tied to the wrong type actually why am I typing all this feel dumb to review two okay replace all one great there was one last occurrence okay compile come on another one merged it has it's done compiling we'll just pull up okay pull boom there now we got our nuggets uh what is your thing update selected value I don't want that container [Music] let's see so container came from there and there's no guarantee let's do this inner it's not null and there let that flow through and then let's test this out see how far away from gold we are I think this will get us this might this is probably much bigger than I had anticipated biting off but you know what I've started down this path and more importantly I really really really really really really want it so um that makes it more viable let's see so mdix Tree View two style that sucker inappropriately we're gonna go up to our good pal here and we're gonna come into here and do that can only base a style I'm assuming that's due to lack of compilation and that the designer has just lost its mind there should be no way for that to happen [Music] I can only base a style on a Target type that is based on type oh because it's um got it got it got it got it got it got it it is unhappy that the style I've selected for despite having identical members doesn't know what to do about itself okay okay fine fine two can play at that game two can play at that game we do this we do this and we go here and we do uh WPF Tree View two boom and then we slap a two on the end of this we go back to our defaults and we slap a two on the end of this and then we relaunch and everybody is happy at least I am happy Tree View does not exist in namespace what did I do wrong no true view two course treeview doesn't exist in that namespace feel like we are not communicating with ammo okay control template Target type does not match oh blah blah blah blah blah blah blah you copy more of it ugh you are killing me okay fine uh let's see Tree View two [Music] um boom anything else I want to complain while we're in here I'm realizing this part name that we've put on here is very awkward I don't know why we did that okay is selection active was registered as read-only and can't be modified without an authorization key that's interesting hey thanks for the follow like or listen trying to build a Tree View control with multi-selection I have abandoned what apparently is the well-trodden path and decided to go off in the weeds at least for a moment to figure out how badly this is uh uh so I love that this says without an authorization key showing love I appreciate it okay what did what did we what did we do here set value yeah I get that we did that that was my fault is selection active I wanted to set that property uh uh you know what where are we inside of here um Set current value collector is interesting so it has no way of setting it ourselves you know what for now we're gonna do this because I assume we can cheat a little bit of this okay so aside from the fact that the selection clearly doesn't work because we've commented everything out and that the uh the the theming colors are not coming through aside from that we've got a custom Tree View Okay so let's let's continue down this this crazy mode for a moment because this might be worth considering okay show oh and thank you for the subscription as well I appreciate it uh let's see here selected value all like all of these selected things just don't make any sense but I don't think they are the key thing to change I would like to find I assume change selection is what's triggering when I click on when I click on the right click on the tree item what happens what happens first of all light mode Nikolai if you're watching it'd be really cool if there was a command line argument for these two uh not to say you have to do it just saying it would be cool okay I click here that does not trigger change selection so I believe there was a handle Mouse button down we want to grab it here when I click oh uh uh this method is called when Mouse button down on Tree View item and also oh oh I hate this so very very much because this has zero references the reason why this works under the regulatory View is because the regular Tree View item can do this because the regular Tree View item references its parent Tree View and can reach back up to do the oh you suck that's why everybody creates a secondary selection property because the built-in stuff is just garbage for it ah see now I understand I don't like it but I now understand it so that would mean then that the item container is the this guy here is our problem child you are our problem child well we started down the path of crazy let's continue down the path of crazy for a moment how how how bad is it like how bad could it be it could be pretty bad that's a lot of stuff but but I'm hoping it it terminates here so let's just hypothetically consider for a moment what happens if I slap a 2 right there and there and then the whole d-type thing dies we this time I'm going to do a find and replace rather than being a and type them all myself because that was just stupid uh uh yeah replace them all there we go and then let's collapse you okay so this one that just becomes false because I'm not interested dealing with the boxing problem right now and then automation properties don't care is selection active property I think what we established is don't have access to it because it's internal is mouse over property key also probably don't have access but we're going to do that instead and then visual state does not exist in current context excellent I was worried it would be easy okay let's carry down our merry way really quick uh let's see Tree View item two Tree View item two Tree View two let's go here this goes here here here here becomes a question mark for nullability becomes a question mark for no ability and then We're Off to the Races and we go back to the top where we had our last problem continue on thank you for doing no ability see this guy is unhappy about the cast we'll do that uh invalidate path on measure so the goal here I'm trying to do something that I thought was simple thought it was simple and I'm part of it was a bit of an exploration process to figure out why it's hard the goal is is I want a WPF treat you that behaves like this where I can multi-select and I can control click and I can shift-click and I can pick the items that I want that's what I want huh I'm curious now large swaths of Visual Studio written in WPF I wonder if the test Explorer is are you a WPF element oh look at that you are well hello what do we have here how did you guys do it how did you guys build this up Okay so we've got a virtualizing stack panel list view item scroll viewer list box Chrome tracking list view you wrote your own tracking list View that's interesting and they did it specifically so they could have these columns Ah that's interesting can I have your code please might have to borrow some of it um they've got a style this is a nice little control I'm very disappointed you guys didn't release this anywhere so I'm pretty sure they didn't I've never seen it before so this is the tab content control wrapped list just looking at where this this guy all goes because sometimes it is difficult just gonna take this and this exactly exactly I just I just need to borrow some bits of it table control ah so that whole thing is a table control test window table control this looks like something that was hyper built for this particular use case I kind of want to borrow it do I I don't know if I really want to take on the entire table because they've got the Sorting up here which frankly would be nice like this this type of setup because this is very list viewy so it doesn't shock me that that thing is a list view okay I've just decided I now want to have my exploration be this thing so uh gimme is the next thing so I would like to do Microsoft Visual Studio uh test window uh dot UI no where are you where are you I'm really starting to wonder why my I suspect because bear in mind WPF released in 2005 like no is that right hang on when did it release it's Ye Old 2006. I missed by a year I was close so at the point they built it they were building a replacement for Windows forms like the bar was not that high yeah it's it's probably horrible that I could remember that far back the only reason I can get kind of close to that date is because I started doing um c-sharp work in 2004. so that was the first time I was doing any sort of.net I had dot internal somebody already knows the answer gracias gracias gracias okay and then we go and we grab uh insert decompiler of choice and just gonna let me just make sure I'm on a clean State there we are and then I think we'll grab this one's probably as good as good as any okay now I would like to see your I would like to see your code for starters uh let's see uh let's see this guy here almost 20-year anniversary yeah now I feel really old I feel very old shouldn't but I do uh let's see test window but I I really just want to grab Visual Studio test window table control so I want to look um this is not looking like it has uh uh there may come a day when people younger than WPF are working on WPF applications oh oh dear okay Joshua you're making me feel very very old now uh which is it's actually telling because I uh there was a a threat I was following online this morning where some people were complaining about a lot of the issues with win ui3 and it made me sad because I I had like I have high hopes that win ui3 can finally be the the Great desktop development platform we want it to be but it it feels like they keep trying and WPF keeps Trucking uh so where would you be then where would I find you if not here let's go back to that um open path what else she got what else she got for me uh uh let's try this one you come here what do you got see test window UI ha ha uh no not quite getting closer though uh let's see test platform test window core you have what I maybe are you core what does core I have found you gotcha now were they nice and did they leave me the bammal for this as well there's the strings uh they did they did they did well they left me something I have a hard time believing this is the sum total of the user control it's also surprising to me that it's a user control but that's a different one um table control styles text column look at that you guys were so nice and left me everything I wanted thank you Styles table control styles and this is here that's not that much I'm just surprised that it's so little oh here we go here we go this be what we're looking for this is what we are looking for this is the big ugly thing so it's worth noting that um when looking at bammal which is compiled xaml tools like the nspy will try to decompile it and put it into a nice XML form but it's just like looking at decompiled C sharp you can never be confident that it is perfectly correct um it is with all decompilation it's not a it's not a two-way street it's a best guess when you go in reverse it's kind of like driving a car when you're only allowed to look forward sometimes things go poorly oh see I guys guys stop that stop that I have a long-seated hatred of a lot of things in WPF where I want to get a job on on various uh teams that work on Visual Studio and I'd like to go in and I'd like to fix all of the hard-coded colors and sizes and then quit that's it that's it because I run my visual studio with my font size bumped up because I do so much presenting and so I just I've just gotten used to it the problem is when you bump your font size up things like this are garbage absolute garbage so the only time you should hard code a height or width in your WPF app is when you have absolute confidence that the contents inside of that control are not going to change size if they can change size you want to find a different alternative than hard-coded width and height Min width Max height those are things you can use those those are fine give it a range do something star sizing dock panel grids they're all your friends look at all this lovely lovely stuff now the big question is is it worth taking this is it worth taking this so what did we identify was the child control that was actually the most useful table control View uh let's see where is table control View is that not in the same namespace am I my my blind or stupid uh let's see test window oh it's up here cable control holy cow this is why they never released it open source holy cow they they even implemented their own delegates man oh how lovely guys how lovely bulk observable collection oh my word it's an ad range and a bulk operation and oh wow yeah you guys reinvented the wheel got it got it got it got it or maybe the wheel wasn't there to copy from so much interesting stuff in here okay must not get distracted must not get distracted I am not distracted oh uh table control view t t table control View oh tracking list View I'm like why am I confused tracking list view this guy this guy bass types list views so they do so they build theirs deriving from list View and worked backwards from there Ah that's clever because if you build off of list view you get the selection for free because if we go and look down here at lists right so we've got a list view bing bing bing bing bing bing bing bing bing okay so if they built off of list View because then they picked up all of that stuff for free maybe this is a better option maybe this is a better option is they then hijacked this overwrote it gave it their own collection okay yeah I agree list view does make some sense okay I want to go Snoop you're in the way go away um I want to take a look at claps these guys up I want to look at the style on this tracking list for you I want to see your template uh it's probably here if I search and go uh tracking list if you so show me a style set on this guy Target type there we go okay so you got some resources you've got a boy I wish I could collapse these things okay so it's the last and still is the last style in the whole thing it's not that big okay great so there's a in the style there's a research dictionary with a style targeting the scroll viewer scroll viewer is doing some stuff to be party that's all fine great don't care um grid view column header they've got a style for where they've set up a bunch of stuff on it not too concerned about that either so item container style is the key thing list few item Style they set up a border a background and it's worth noting they've built this with the idea of this is a purpose-built control not not something generic it's interesting that they've got a list view item Style let's take a look at this so the magic must occur here uh let's see they've got a background color which I'm guessing is just for their theming support whatever they're doing there overrides default Styles great great great control template that's a real short control template their control template is like nothing wait that's the end of the style wait what no no wait wait wait huh where did they get the expander where did they get the content I'm missing something I'm missing something this scroll viewer must be doing more than it meets the eye row presenter scroll presenter scroll bar scroll bar no it's not good you header set in the template for the header it sets the item container style but I'm I'm because each of these items are clearly hierarchical right like that's a thing that exists why well if all of those things are hierarchical how does this this view item there we go ah this there I must have missed an assignment here Ah that's what I missed that assignment right there okay got it there's the control template okay this makes slightly more sense so we've got a border with some stuff wrapping around it a Content presenter that grabs the entry content inside of it okay is selected it change toggles some background and foreground stuff great where does it get the thumb is the question because at a certain point there has to be a thumb in here somewhere or an expander or or toggle button or something that's why I'm missing the is expanded I see the selection and that's fine there's got to be an ex details expander control span path what is this inside of details expander control okay so let's move you to the side for a moment Visual Studio come back I would like to find my Snoop window that goes with you I've lost you there okay I want to know where that thing is So Pro tip uh with Snoop attached I've just put my cursor over it and then Ctrl shift Zero's in on on it in here okay so there's the path so how is this thing structured so there is a tracking list view item so there's the list view item list view item wrapping border and I think that's what we just found I think that's what we just found before list view item so we can come over here and we can do list view item wrapping border a shoe item wrapping border so that is the border that wraps all of the items in the list view template great find that makes sense inside of there there's a Content presenter great that makes sense entry row border how did we get there entry oh this entry content is what's getting us there and that is not clear oh you're gonna make this hard on me aren't you okay so [Music] is tool tip show tool tip close tool tip wow you had to manage all of this so but if we go back to here we are not that far foreign we are not that far if we look at building this off of a list View with the concept of perhaps collapsed rows because I'm thinking that if we do something to that effect we could make this work a lot better okay okay okay okay okay okay okay so we're gonna do I think I'm going to abandon my crazy mode of hey let's just re-implement Tree View because that I think has now proven proven what the problem is okay I think we're back to here so slight detour long trip but at least I learned something list View okay so we're going to go here instead and I don't know if any of this stuff is relevant anymore um and then we're going to go with public class uh multi-select uh uh preview item list view item we're gonna do this we're gonna do this I'm gonna go up here and we're gonna make you a list view that's done that's done we get rid of this we don't need this anymore we'd get rid of this don't need this anymore I don't think like we don't have to manage our selection stuff anymore I think what we manage instead is visibility and I think that's where it gets more interesting so because this is going to need a uh uh what a prop DP uh let's see pool uh is expanded we're gonna need something we're gonna need something like that to start there so we go something like that something like that something like that something like that okay that gets us there and then we need to make sure that this is the one that's used override uh uh let's see get container for item override and then we need to override is uh yeah this so this becomes uh item is a multi-select preview item boom this is nullable this one here becomes uh return new multi-select preview item okay okay that gets us there then we have some of the harder work to deal with on the other side of the fence because now what we would like to do is I kind of oh we're gonna leave all of this here for the moment uh except for this this is dying I would like to steal this style because this style is going to be very close um we're gonna do design multi-select review and then this becomes let's see WPF multi-select Tree View so that goes like that we go to our defaults now we adjust that [Music] See Tree View 2 is now axing dead this is still alive and well but we want this to be uh Band-Aids getting in the way uh let's see multi-select what did I just call that thing that I want that you go there boom boom boom okay that goes there that goes there that's set up you go away I don't care about you anymore you are now a multi-select review and then I think we just want to replace all of these things in here and I don't want to think too hard so we're going to do this go with f and we are going to replace preview item inside of here with material design uh uh whatever I call this like that and no I want you to replace in the selection what don't lose what I was telling you to do in the selection do the replacement thank you yeah I get it go away shut up okay now this is probably not going to be perfectly accurate because it doesn't have header like the other one did it's just gonna have content that's okay because we are going to have to bring in the concept uh because a list view I yeah header doesn't exist it's what is it content let's see content content content content we're going to run into the issue of hierarchy here very quickly but let's get at least a top level list working then we'll we'll add it in as we go okay content content content contents content content the only reason I'm not finding and replacing all of these guys is because I kind of want to I'm looking for the the hierarchy of these on the way down okay content is set multiple times yeah this is what worries me why do you think content is set multiple times oh because content is itself the content okay got it don't need that don't need that don't need that don't need that then we don't need that and we don't need that we are probably going to need to come back and change up this control a little bit but okay already has a child and cannot add right so this is not surprising because that is handle that for me real quick so we're only going to be able to get the top level items in initially because we haven't added any sort of hierarchy to our object model specifically the items inside the list box or the items inside the list view because the list view expects to only have single items uh Tree View control template does not match get it I screwed up I get it I get it I get it I get it I get it uh let's see it's probably about to whine about the items container style two I imagine we might not need to set the virtualizing but okay so aside from the fact that it looks like crap it at least renders progress okay we're gonna ignore the ugly blue for the moment and I think we're going to try to add in the hierarchy next because I think that makes the most sense for each of these so the items container style for this guy is where are we even setting it there's template we aren't even setting this thing so let's do uh Setter property items container Style um or actually we don't set it in the other place either we just let it flow through I don't think I like that I think I like being a little more explicit so let's grab the tree view item this guy you sir become new friend I think you have to go on top because we're going to reference you and then I want yeah yeah yeah yeah uh let's see vpf multi select preview item material design multi-select Tree View item and then we're just going to collapse all of that uh let's see and we want that control template doesn't freak out it's not going to have enough information to work with for example the header isn't going to be able to be bound we might just have to go and add header in real quick it's like a tree view item real quick what did tribute because we kind of want to structure it that way and then has items that we're going to want as well so we're going to want our item to have a little more of the setup as well and virtualizing stack panel we probably want that as well that gets us to there that gets us to there if I do nothing this just floats in so you can do it like we did Tree View but I'm not sure I actually like that because treeview does it by an implicit style and I kind of like being a little more explicit cdefghi no that is not correct copilot Copilot item container no copilot bad bad Copilot it's the thing I just wrote a second ago that's the thingy I wanted to reference okay uh um so let's take a quick Gander at what that guy is set up as because we want this to look review item we want this guy to look somewhat similar in regards to this uh um so I think we're gonna want something about like this we're going to want to do something like that and then because we're using the same template that should just work and then we want to set up the um the header item and the content appropriately so we would like to set up oh they don't set it up because it's a headered items control got it there's nothing fancy about this there's not a lot fancy about this what if we make this thing a uh uh headered items control yeah I think I like that because then we don't have to do a lot of the implementation and then when we go back to here this becomes better this becomes header pile let's make sure see if we actually compile because that's gonna be a telling thing but I think by switching our Base Class we're going to be real close real close content doesn't exist yeah I know it does renamed it again come on keep up with me we're renaming this okay so that build succeeds let's see if this thing launches appropriately okay they cannot find material design expand collapse toggle style okay so that's probably because we copied a style and didn't uh reference it appropriately close you I'm going to start with this where is said Style exists in Tree View oh um hey see films I'm doing great we are attempting to build a multi-select tree view in WPF because it does not exist and we spent the first part of the stream with me just figuring out why the problem is hard because sometimes sometimes you need to uh experiment and figure out and answer the question why has nobody else done it what seems like the obvious way we tried it we figured out why nobody's done it what seemed like the obvious way to me turns out it's hard and difficult and then conveniently we took some inspiration from Microsoft because we we took a little Gander at the test Explorer and realized this is kind of a tree View this allows multi-selection I want that and then we pulled open their code and we took some inspiration and decided you know what let's look at how they're doing it okay so that got us I mean not great but it got us close-ish I guess okay so that that kind of got us a little bit of the way there um yeah so this here is a second if I can find my browser this is the material design in xaml Project uh of which I am a maintainer and I I really want this multi-select review to uh um to exist inside of it so that I can leverage it for a uh an Enterprise E project adding things into a database that sounds fun okay let's see here so this gets trying to decide where we go let's go let's go down the path of expansion here real quick because I I kind of feel like making it look Tree View is probably the first priority it should look like a tree View okay so let's start there who needs selection we just have to re-implement a tree View we started thinking that the easiest thing to do is going to be Implement um selection and now I think the easiest thing is re-implement preview okay well the good news is it has items I'm a little confused as to how it knows that uh I'm deciding what is a board game hangout and not just a board game store ah sounds very similar I started building an app a couple streams ago called rentopoly for keeping track of who I've loaned my board games out to as well it's actually very interesting trying to put together an object model around board games because it feels like something that would be that would be easy but with everything there's always these weird exception cases I think that just speaks to the creativity of board game designers okay so what have we done or what have we not done more accurately um so we've clearly gotten here we've clearly gotten here we uh okay we're gonna change this up because this is dumb this should really be part scroll viewer and it should be cased like this because that's normal WPF boom and then we're gonna replace it down here there we go okay so that that cleans up a little bit of naming um I don't know what BD is being used for let's just check not being used at all excellent we're going to burn that down then um burn it all the way down because why not and then see okay great and not all board game stores are board game hangout store yes very true so I think the best ones are uh do magic Wars as a board game hangout store oh see this is where it gets hard this is this is the hard part is what counts what counts as a board game does there need to be a board involved or similar because there's there's also weird cases like because I was accused of being old earlier I also enjoyed pinochle right and there's places where you can go and hang out and play pinochle do those count as hangout stores as well um I'm tempted to say like for me if they let you sit down and play games and they also sell games I would count them as both but again that gets real blurry there's been a couple restaurants especially in our town recently um that um where they've kind of started to combine the idea of restaurant or like Pub and board game which is an interesting idea but again then you'd have like a hangout store but not a board game store because because they don't actually sell board games oh thanks for the fallacy films um Okay so we've got where did it go why am I oh it's because I'm looking at the wrong Style okay that's why I can't find it I'm looking at the wrong thing uh have you ever been a dungeon master actually yes I I do have a uh board gaming group that I play with um every other week and currently playing in DND 5e and it's fun and I I am the DM partly by default my wife actually really enjoys the the role play storytelling aspect of it um however she doesn't like the stain up late aspect of it so she often enjoys helping plan out the the story side of things and then she goes to bed and then we stay up late playing because that's what we do but I I have fun with it I have to be careful how much I say because I occasionally my players have dropped in on the Stream uh okay so has items is showing up expander visibility boom that is actually triggering so that's how is that working though we don't actually have a has items property do we header control oh items control has a has items I bet yeah it does there okay that's how it's working my twitch stream plus one inspiration uh [Music] uh okay so that that is how that gets me there okay so that okay that all makes sense I think I think all of that makes sense so the question though is why are we not getting when I click it and I expand it why am I not getting any expansion occurring and I think the answer likely lies in how and because of our Base Class that we've subtly dropped so hold on where is our thing there is our toggle button Mouse over selection border content grid content control where is our items there it is there's our item Source okay so this is the guy that's expected to be populated when when we expand and so if we hunt this guy do so he toggles opacity items host visibility so the items host should be toggling from the storyboards and the storyboards fire based on the visual state of the object moving in its expansion States however we have not implemented anything that changes the visual state of this object so the only visual State changes that it's picking up are the ones that exist from the base class which are only going to be related to selection that's why it's falling apart okay now we've got our bearings or at least I've got bearings boom [Music] okay so we want to do something in here where we actually change visual state so just to be clear so it's uh visual State manager right uh what is it change or set visual State what it What is the there's a thingy in here that you use to change it go to state that's the magical incantation right so control this and then you need to use state name now my state name and then you know whether you want to transition right so is this animated or not so what we need to do is we need to toggle the the visual state based upon when this property changes but step one we need to make sure that is expanded is actually appropriately being bound up because if it's not this is all for nothing the toggle button uh [Music] is checked is bound to is expanded on the templated parent the templated parent of this will be the tree view item the toggle button is appropriately bound so if we look at this guy and we take our lovely friend Snoop and we go and look at him what we should see is on this item as we toggle it this is expanded State should be appropriately changing that is what we wish to see item expand is expanded right so ignore the binding errors those aren't the things yeah okay so that's working just fine okay so that works now we need to change the controls visual State uh let's do visual State manager go to state I believe we've done this in about a billion different places foreign I want to grab we have a transition manager that allows people to disable the animations if they don't want it and so I just want to make sure we steal that borrow borrow borrow with no intent to return uh on is expanded changed generate method foreign oh shoot I forgot I told the guy on Twitter earlier or the website formerly known as Twitter that I would answer a question about dialogue hosts just saw that just forgot about that wasn't dialogue host it was popping multiple windows um okay so that goes there so state name we're going to need to grab this and we're gonna use this um use a mySQL database that's not a bad option especially if we're getting stuff stood up I actually did a bunch of MySQL a very long time ago the Ruby on Rails app gotta be careful I'm Gonna Keep dating myself um there is a there is a CH yeah this thing we are gonna want some of these thingymabobbers I want these things and I want to set them up appropriately so that they line up with what we have here and I think we're going to make them Match Tree View because that would make a lot of sense expansion States I'm using PHP yours only as old as you feel amen though I was in a I was in a meeting this weekend and when we got done I looked it around the room and I went hey Nabbit there was I think eight or nine of us in there I'm like I'm one of the top three old guys in this room what the heck is going on which I had very little room to talk because a couple of the guys were significantly older than me so that made me feel good probably should have but it did um and then this we're gonna line up with Okay so we've got the groups in our attribute these are the transitions visual State expanded and collapsed so these strings here have to match are you doing Visual Studio stop it uh uh boom let's see so let's go with expanded and then this becomes expanded okay and then we are going to do uh was it collapsed oh toggle State thank you and then you become collapsed you become lapsed and then we are going to do uh e dot new value well how about we do this if uh edu value is Bool uh is expanded and is expanded do this and this will be the expanded state name otherwise to be needful and that goes there this will be the op-ed stop it stop it lapsed can I not spell oh two else got it uh what are you complaining about can't framework element uh so uh if D is element it's not an element we have no b no reason being anywhere in here and we will just do element there element there okay so that should be changing our visual States we should now see the thing expand out underneath it should be animated it should be pretty and glorious and everyone's happy bum okay so we go there rapes for us I don't even know if that's right but I'm very excited I really wish the uh we might need it we might have to fix the font color because it's really hard to read okay I don't remember were we supposed to have more than that underneath fruit we have an item that has Apple uh uh let's see here I think oh what why am I guessing we've got it right here here's the original apple banana grape is supposed to be there Okay so we've got we got a bit of a bug in that uh that doesn't display correctly but we change things up a little bit and I just want to check it and confirm so we might need to to yeah so this one is changing to be content and we really want this to be header again because that's what it was before okay collapse you up I don't want to look at you anymore so that that one we need to be setting the header on grape should be fine surprised it only showed the one Christ had only showed the one um we might just have an issue of it's a headered items control but that yeah so we fixed part of it oh that's why we did the implicit um [Music] yeah got it that's why I Now understand I Now understand okay so that's why you are set up the way you are so we're gonna grab you and I think we can come back up here and wait preview item to view item preview there we are we can turn you off because we're going to head over to here and we're going to go up to the defaults we're going to go here preview item review item and Leverage The implicit I bet you the lack of an implicit style targeting that new control type is the issue it has no template therefore it just fails to render anything bench that's it oh look at that I win I win we have a tree View [Music] kind of feel like that's ugly with the way it indents grape yeah so there's something something messed up about that but that's okay that is okay probably has to do with the binding stuff that is failing because I assume we have binding failures yeah we got it we got a couple binding failures we should probably yeah yeah so there's some biting failures a few things are failing to buy not a big deal not a big deal we're fine we're fine we're fine but then can I okay that's what we should probably add in selecting an item next that's okay actually before we get carried away before we get carried away what we really should do is we should go to our good pal get cracking and create a branch uh multi-select preview uh quick Gander at these things I don't need that I do want that actually you know what let's check that in for the moment uh let's see that goes there we can probably change up these defaults a little differently I'm realizing we don't have to do them this way we can do them like our other custom controls um and then all the new stuff and then that stuff okay whip okay so we got that okay we got a safe point I'm a pretty happy person when I use speech uh I love it I love it it's been ages since I've actually used PHP I've never done it professionally but I did a bunch of it in college um I even was on a network security team and part of what we had to do was uh effectively secure a PHP website MySQL real Escape string function was our best friend because the site we were given to defend was loaded with vulnerabilities uh okay so do okay so now we want to go after selection because we want to have this concept of is Select so one do we even have that concept built in yet because clearly The Click is working but that's just the ripple effect uh cool students sorry you know CSS uh I barely know CSS I will say that I I know it well enough to get by and sometimes even then I debate if I actually know it that well okay so we don't have selection as a thing so that's exciting um so that's that's part of so so that would be why that doesn't work so let's add in selection and will not implement it stupidly like the tree view item did uh prop DP what was the most clear coding language clear programming I'm going to assume that this is going for a pun reference and not an actual like Clarity type clear challenge Swift because it's hard to see I don't know if that's a good one or not uh let's see bull uh is selected and then uh multi-select Tree View item and then this obviously goes to false so it is worth noting the thing that um you saw the built-in controls using with the Box booleans the reason they do that is because this actually causes an object allocation because property metadata's default value parameter is of type object and so every time you take a value type like a Bool and cast it to an object even implicitly it causes the value type to be boxed or wrapped up in a nice little container and stored on the Heap the problem is if you do that a bunch that can cause some memory pressure which is why people will create box booleans and WPF that way there's only one instance of said box Boolean and you have a reference oh okay now I feel stupid I should have gotten the c-sharp reference uh uh Okay so is selected is there and I think uh oh we're going to have to do the selection States as well which is fine there's only two selected and unselected so we just need to do both we just need to add those in okay so we're going to add in a couple more a couple more State transitions uh let's see here and I believe I put that uh nope did not copy appropriately uh selection States boom boom boom boom boom boom boom boom boom that's the problem with developers we like So for anybody who's seen the xkcd comic for nerd sniping I I tend to reference it a lot the uh my my strong opinion is developers are only worth one point because we are so easily distracted and overthinking them there's there's another uh XKCD yeah right like this came out at a point where I was um actually taking an engineering class I I was either still in an electrical engineering class or I just finished one it was close to that time and I remember reading this comic and I got to the this this panel and I immediately stopped like a had started thinking through the problem and then yeah then the rest of this happened and then needlessly I I burst into laughter but developers I in my opinion are only one point because they are so easy they are so easy to nerd snipe uh uh let's see here selected state name unselected state name and then we come down here we do on is selected changed send me a message and me a method and we're basically gonna do the same thing gonna do pretty much the exact same thing with some minor altercations okay and then we are going to go with selected state name and then nope nope uh unselected yep I can't type that's okay uh and then yeah that should be fine uh we want to rename this to is selected I think that works oftentimes people will switch these ones up to name of expressions um it's not as critical in my opinion because there's actually no real strong link here but if you violate it you're doing something wrong there's that there's that okay so now we should probably have selection working foreign I'm guessing I'm hoping [Music] why did you open up over there okay light mode and click click click oh why would I expect clicking to actually select it I haven't done anything to set is selected to true right like that's a thing that isn't built okay okay uh let's see override on Mouse down [Music] right does selection typically occur on down or up I think that was on down but let's let's confirm let us confirm so if we go here and we pick on the tree view item we go is selected right and I'm going to click really slow and so down up okay so it occurs on down all right okay uh on Mouse uh left button down hey stop it stop it [Music] uh okay and then we're gonna do something like uh Set current value uh is selected property true I think it's actually a set value in this case set value is selected true so when we click now obviously we should probably handle a few other things but Simplicity first Simplicity first be light mode okay click selection expand selection selection multi selection I just had to re-implement a tree View and then you get selection for free turns out implementing preview now uh why set value over is selected so that's a good point because uh is selected is going to end up doing the exact same thing so excellent um there is we are going to change this up a little bit because unlike how the regular oh oh we should we should we should toggle selection okay so if you're always just set is selected to true you can never unselect that that kind of makes sense and we are going to need to implement because I realized I I'm very happy about multi-selection but like multi-selection isn't that impressive because we didn't ever like we're never clearing the selection so we might want to implement clearance selection because right now we have it and I don't like how we have uh yeah multi-selection achieve on selection to be implemented later um there is this because of the the setup that we've got this guy up here is I don't like how because we've inherited the tree view Styles we're getting that and I don't I don't want that because this is a new control we can break past behavior um and that this is uh where is it there is an item in here that is controlling whether the selection is inside or not uh uh oh does selection mode enum that's a good point that is an excellent point um so it already exists because we're derived from a list View I think we're going to get it for free I think we're going to get it for oh why don't we get unselection for free why don't we get it for free list view item we should have gotten some of this for free but I think when we changed our Base Class why do I have a feeling that there's extra stuff here that is not being obviously handled for me I bet you there is stuff specifically in this vicinity that yeah listview does have um some selection stuff built in like if we jump over to here this is a list view so click click click so it's it is it is unselecting and doing it I think this is a pretty default yeah this is just default so I'm I'm gonna go with selection mode is probably set to um single I believe is the default but it does because we are not a list box item and we are a headered items control this is the problem we kind of want to merge two things together um let's take a brief Gander at list box item because I'm willing to bet there is something going on there that is doing this selection so on selection changed it raises a routed event updates visual state I am willing to bet that this routed event we want to raise this as well because I'm willing to bet that is what list box item um that is what list box item is looking for ah great question why why deriving from list view instead of Tree View so we started down the path of deriving from Tree View the the pro so the whole idea here is the the built-in treeview control does not support multi-selection and I even went to the effort of copying in the the the code from the existing Tree View and trying to beat it into submission the problem is there's a bunch of internal sealed stuff in it that doesn't copy out well the because WPF you pick controls based upon the behavior you want not based upon the look um we then took some inspiration from this guy here and we're like well Microsoft clearly has implemented a a tree a tree type control that has multi-selection well this is a WPF um well I shouldn't say I shouldn't say this is WPF lift system this is a custom control that derives from a list View and so we took a little inspiration from there and went you know what let's head down that route we aren't going to fully Implement like the column headers and that kind of thing at least not for V1 but I have a desire to have something that has this much Behavior um and so that's that is what I want um okay so if we come in here I think what I want to do is this parent selector list view item parent selector what is this doing items control from the container this is public this is all public so we could implement this this is a thing we can do this is a thing we can do uh tree data grid maybe it can be ported WPF yeah I've seen those ones around and people have asked for those types of controls a lot in inside of the the material design Library which part of me is really inclined to bring some of those in but I also want to be very cautious because everything I bring in I end up having to support so there's a bit of a chicken in the egg problem um you know what we're gonna do uh protect it internal we're gonna be generous and if somebody wants to derive from us I'm not going to stop them okay so let's grab the where were we we want to grab this bit of code and put it inside of R is selected changed so list item so we're going to do uh um what do we actually care about uh we well we do need this to be a multi select review item so this is going to be moving up into here that has to exist here this becomes element that goes there that is clearly nullable and then think about that for a moment uh element and then this is problematic because we do not have a these members yet but it's probably good to have that kind of thing there okay so Ray is selected changed automation event hmm so we're going to do this uh Bool is selected gets this actually you know what we're just gonna hard catch this nope nope not what I meant to do that do that do that and then that problem goes away we are going to ignore this one for the moment which means we probably don't actually care about this parent selector currently let's deal with the on selected method because these are just going to be yeah so this is we want pretty much this much I want this much of it so I want to do something about like this and then the region tag dies and then if you do uh let's see Snoopy Visual Studio shows that the Tree items are pivot tree pivot items I agreed because I think if we look well so the the ones that we were actually looking at were the the tracking list view items and the tracking list view so specifically on Visual Studio [Music] test test Explorer and it so it's worth noting I am also on a preview Visual Studio build so um yeah these ones are very much internal so when uh no so when we come in here and open this up if we go and look at one of these guys Visual Studio window specifically this is this tracking list view item is the one that we were chasing down and again it could be that this has gotten Rewritten I know depending on what version of visual studio um like in the last year or two there's been a bunch of rework around the test Explorer so your version May differ from mine um a little bit but then the the assembly that we ended up finding these guys in is uh Microsoft Visual Studio testwindow.core.dll which in my case uh I was pulling it out of here so program files visual studio version preview IDE common extensions Microsoft test window oh solution Explorer uh yeah I didn't even think to look at its solution explorer that makes sense I just I I was making some comment and I opened test Explorer and then I went Tree View or Tree View like um Okay so multi-select preview item we're gonna add an owner for the event raise the event uh uh okay that's all fine expression body why does this take in a Bool if we're never gonna use it I'm very very very very confused why we need this method okay so we're just going to get rid of this method because it doesn't appear to be doing like did I lose something in my copy and paste because that looks like it's just garbage reasons exactly I yeah yeah yeah yeah something about this feels very wrong like am I missing uh huh uh we should probably bring this in we're already we're already doing enough stuff to it we should bring that in why wait why is there XML comment raised when it becomes true um no that's that's an inquiry there's no way that that's actually on sorry I have to look now foreign yeah occurs when list box item is selected so source is out of date because that does not match with what we are actually seeing okay maybe I should have gone to the WPF repo on GitHub and got it there um because this this doesn't make a lot of sense uh okay element unselected oh banana Tron 9000. dead code yes exactly like this kind of I'm very confused at this this like huh huh um yeah so I'm very very confused okay so you have WPF we're just gonna we're just gonna we're gonna go take a little Gander down the real source code uh let's see here source oh boy uh now I gotta remember presentation core refs no uh how about we we cheat and we just do a search list box item please uh uh that guy okay so I am more interested in finding out where is selected I mean that's okay I mean it's still stupid lovely guys lovely lovely lovely okay people people people we're we're not going to take this whole sale we are going to clean this up because this is this is not okay this is not okay Okay so handle selected change I'm questioning why this needs a parameter at all like yeah I okay yeah we're gonna okay so if new value oh yeah yeah um we're gonna come in here and go raise event and do this and this becomes this and then we aren't duplicating stuff else we will raise event we will do the exact same thing that this guy was doing copy paste enter this becomes this and then we're actually like using all our parameters and we're not going to pass like extra stuff around and be wasteful and do all that kind of chat like and then this goes away and we just do that like am I crazy that feels so much better I must be crazy okay so that feels a lot better to me and in fact if we're going to do all of that why don't we just do why don't we just save ourselves an if condition and just like do do that instead and then we don't even need that you're done like okay okay so now let's see if by raising the appropriate routed event if list view will appropriately catch it and handle it and do all the right things for us because that'd be really cool and region directive expected that means I copied in a region that I did not mean to copy yeah yeah I'm seeing a bunch of warnings about my XML comments there's gonna be some there's gonna be some cleanup around this code light mode expand select select foreign [Music] I am wondering why we're still back in the same state we were in before which means something about list view does not does not do what I think it does uh let's see let's go here to two this is just all the automation peer stuff but well but now that we are in here uh uh oh but this is a selector does listview derive from selector I can't remember don't know if it does it does very indirectly and I guess the other question is what is our selection mode so foreign I want to set it to single for a moment just to just to confirm that this is not doing what I think it should be doing kind of hoping it would just handle the event for me and be done with this but there there okay so that is so even with the selection mode change that's not uh doing the needful uh let's see can't select multiple selection changed validate all of this stuff so how do you pick up selection set selection selection change blah blah blah yeah but what kicks you off that's what I want to know uh see that's set selected items uh uh that is not helpful and GitHub where are you taking me stop it stop it okay uh let's see here so filter symbols select so set selected items on selection changed virtual function is called when selection changes this is overriding from the bass and then it's doing some work so list this is list box but that is also coming from the base class which is on selector Xbox base inks canvas ribbon ribbon selector so this comes with on selection changed oh was the other thing so what triggers in this file what triggers on selection change invoke selection changed yes what what invokes you that's what I would like to know how do I get here end that is not useful selection changer end okay how do I get here selection change end so set selected items is one way in selected items collection changed so changing the things there but I'm I'm confused as to how list box does it self a second I'm going to take a brief Gander I may have already cloned this I have that would be really really convenient have standby standby we're going to look at this in better mode because GitHub you're nice but you are no IDE a come on where are you there we go Okay so uh meat Shield thanks for the follow okay we're gonna dig into WPF here for a moment take me to selector yeah that would be great thanks okay so yep yep stop stop stop stop stop stop selector has a thingy in here called end selection begin end okay so we would like to find all references um and actually maybe we'll we'll go to list box item right this guy here this guy did stuff and he has his on selection changed and we could even start with Mouse left button down handle button down takes me to here selector UI get is selectable I didn't even know that was a thing of course it's internal who cares uh oh you dirty dog you dirty dirty dog notify list item clicked and so this so it has the item calling into its parent list box okay so show me list view item how do you work you call into list box so all your implementation is going there does that mean that list view is in the same situation list view derives from this box I'm guessing you don't have any selection stuff in terms of behavior you don't okay so list box is functionally what's driving this so the fact that we are not deriving from list box item means we are not getting this invocation when in vote which is what is biting us um and this is of course not public because why would you make it public that would be way too Bloody easy there's only one reference and it's from here interesting Okay so boy you guys made this hard so that means we almost need to re-implement this we almost need to re-implement this because it's internal and there's no other way around it that sucks okay we're we're gonna we're gonna do it because darn it I want this to work [Music] okay so back up here we do this we do this we do this now uh we're gonna do protected virtual internal we'll do that uh okay and then this is going to be multi select preview item because darn it if somebody wants to override this I'm going to let them I'm gonna let them okay so we're gonna have to do the needful there on various things and so the question earlier about are we going to implement selection mode uh apparently apparently so I'm gonna hope that we don't get bit too badly with this um uh let's see Set current value is selected [Music] okay oh and we should this oh we should have been leveraging oh hang on is that actually going against the same thing it is it is it is that's interesting where's your is selected [Music] is selected ah we probably want to mirror our is selected like this um just just to be consistent because I just did a regular dependency property like a fool like a fool okay and then as I was realizing we didn't do the binds two-way by default which we probably want to do uh so that goes away um this goes away um we're just gonna get rid of that because that's dumb uh okay so we'll do that add owner multi-select review item gets me into there that gets me into there okay now we go back up to here so that means that we will be setting the same property got it update anchor and action item don't know if I need that uh set initial Mouse position don't know if I need that uh let's see and this is going to be here this is going to be here and then you know what we're gonna just comment these out because we're gonna get we're gonna get this going for just the one initially and then we'll then we'll come back okay so this needs to be invoked on here in the same way that list box item does it so this guy here because this has on left button down we want to do something about like this okay so we were close we were close um and they have a handle button down we can do something we should probably do something similar I'm noticing it also has the focus uh stuff in there as well so we will pick that up while we're in here we are not going to do the is UI selectable because well you made it internal darn it and then parent uh parent preview we're gonna do and let's see that goes like this this comes across uh um we can just grab both of these let's see I would first Define your true view item with the hierarchical data template uh create tree item view model class that represents in and setting data context in your main window that is a um that is a wonderful idea the problem though is that that assumes uh an application Level view of it in general control libraries can't can't assume data context or even mvvm and I'm trying to build this even though I want it for a specific app I'd like to build this to to put it into the material design Library so that's part of why I'm jumping through some of these arguably ridiculous hoops uh let's see what do you think of vs code versus visual studio uh the so I favor Visual Studio a lot because Visual Studio is a much more fully featured IDE it's been around a lot longer however um I keep vs code around a lot and use it quite frequently there's a handful of things where vs code is significantly better A lot of web development vs code is better um various language support vs code is better like Visual Studio is really good at dot Netty Microsoft things but the moment you kind of step out of that ecosystem Visual Studio code runs circles around it so it is quite good there it it's multi-cursor support or vs code's multi-cursor support is also significantly better than visual Studios so there are a number of times where it can be quite advantageous to switch into vs code for opening up um for for doing multi-cursor stuff so I will also occasionally jump in there because I like its interaction for if I have to do a lot of like text manipulation with regex or similar you can get similar things in Visual Studio but vs code is just a little it feels a little nicer so uh I I think both are useful depending on what you're wanting to do uh let's see so this becomes nullable which makes this nullable which makes this an expression body member which makes you an expression body member it's the problem with the WPF stuff being so old uh let's see this goes here and actually we're gonna just pattern match this uh uh uh Tree View go like that go like that go like that and we're gonna go with preview boom boom boom Okay so all of that but now we should have single mode selection I think working I think all my excitement about having multi-selection working and all I'm gonna get I'm gonna go back to single selection but we will hopefully get the rest of this okay so light mode because we haven't fixed that yet oh single mode selection works okay okay we're good we're good we're good okay now let's let's finish out the enum [Music] uh let's see make toggle selection that's what we need next yeah okay shamelessly back to stealing from Visual Studio uh list box I want whatever this thing is doing uh um this is not doing enough to Warrant a method make toggle selection this is literally just doing item is selected gets not item selected with some fancy boxing okay so that is really not doing enough to warrant uh enough so uh and they were just to be clear yeah and not item is selected so not item is selected boom so multi-selection is about to be real easy real fast this one should work really nicely because this is functionally what we had a moment ago so I'm going to just claim that I implemented multi-selection first there there there there there there there there there oh interesting it doesn't want to do the child items I wonder why those ones don't like don't like being selected that's surprising let's catch it for a moment I didn't test the I didn't test single selection with them oh interesting they aren't huh they aren't trigly triggering Mouse down click oh they don't have a parent Tree View uh um why is that the case do list box items they don't derive from yeah they're just content controls they don't drive from selector yeah so how how do it work how did listbox item how is it able to attain that is it calling a different overload than I am get parent is item its own container so this just looks at the immediate logical parent get items owner this is probably an issue with my template layout I might want to step this uh let's see uh oh this is the WPF Library let's try on mine all right just to make sure I am going to the same spot right oh that's that's disappointing um parent selector is null it's not that even that the tree view is wrong it's the parent selector is even null which means this guy here does not I wonder what get items owner is returning so come on open my immediate window let's go Visual Studio open thank you oh you are you are struggling buddy you are struggling I think it's time to pass out have a good night you too I'll see you tomorrow Joshua get items owner hmm oh it is midnight isn't it dang it hate when that happens get I so get parent it's grabbing the parent and then asking for the item's owner what is my items parent I guess is the first question what is his parrot so let's let that go for a quick moment just a hot second come in here what is and it's probably related to why the grapes for us is nested so deeply okay you you will pick on banana okay so here so if we just walk this kind of functionally in our heads for a moment when we call from item container we're passing in and we know we have to be passing in a tree view item foreign so that the tree view item comes in here cast to a UIL element true comes in here gets parent the parent is a virtualizing stack panel which is not an item's control but this is The Logical tree helper so this might be expected to be returning uh let's look up what this returns um if I come here here click oh uh continue and then if we look up what does logical tree helper of this return so it does get back an item and what is it giving back it gives back fruit so that's so it gave back this as The Logical parent so inside of Boom so that will not be null it will then check if that is a generator host and if the item is its own container I don't think that's expected to be like who implements this go to implementers combo box data grid entered items control um we we are a list view not a headered items control and I wonder if that's because we've got that disjoint if that's what's breaking us uh let's see foreign change prepare items control I am wondering if that's part of the issue is we've derived ourselves from list View wanting to pick up list boxy Behavior which in some cases we are and in some cases we aren't the question is are we derived from the wrong class no because we want the selection built in if we derive from something lower we'll lose that and that would be that would be it pitiful so that's why it's failing is parent selector foreign selector is not what one would expect so I guess then the other question is how does tree view items support it because Tree View item should it's a headered items control which is kind of which is what we derived from but maybe that was maybe that was a poor choice what did they derive from just out of curiosity they being Microsoft uh let's see Tree View tracking list view item they derive from list view item they derive from list view item interesting I don't know if I like that at least for ours theirs was very much a purpose-built thing um let's see selection I'm looking for Mouse interaction Where is the because I assume it must um Mouse left button down there so what do you do handled and is enabled Focus it calls select so it's not parent Tree View yeah so this how did you implement this uh parents not equal to null ah this is what we need something that iterates this is closer to our implementation that we want parent items control parent Tree View item we want something in this vicinity something very similar to this that is why we are breaking okay so we are going to steal that come over here we are going to do this and we are going to do this and we are going to do this we're going to do this and we are going to do this and not grab the region did not grab the start region so we'll clean that up and then we'll do expression body member there we will make you and then we will do there and then we want you to be a multi select preview there there and then you get declared as nullable then you go away okay I think that gets us because that should then work for the nested items so that was why listbox didn't care to go up more than one oh and we can do the pattern matching suggestion stop it stop it I know you're compiling stop stop it I want a pattern match pattern match is fun I don't match all the things okay uh something like that yeah pattern matching is yes it when it first was introduced it took me a minute to kind of wrap my head around it but now it's it's one of those features that once you get used to it it is really hard to imagine going back without it okay so now I have that and now I can click at different levels great okay that's the multi-select Let's test the single select and that should work at different levels and that gets us into a much better state okay so single selection there oh interesting wait didn't we see single select worker oh single selection isn't working in the nested items only at the top level okay okay so in this one no uh I don't I my intention is not to mirror that behavior um however uh if somebody wants that behavior I would expect that they should be able to implement it um one if they're doing mvvm they could do it on the data side of things all the way down the other option is I'm trying to be intentional about not making things sealed or locked away so that you could hijack coming in and dealing with the um expansion States uh so technically it should not be possible to select Fruit by default right unless fruit is a valid option um I think Fruit by its uh so with uh the selection mode I would expect any single item to be selectable I'm basing I'm basing that entirely upon how this works here where you could select it at the top level and ultimately the what I need it for on my project selecting a a container item would be valid because that's the equivalent of like selecting a folder to indicate that hey I want to perform this action on everything in that folder this and all of its children basically so I so aside from the fact that that's not appropriately unselecting um so let's grab this and we should figure out why so if item is selected uh keyboard modifiers is control Set current value to false otherwise do nothing I'm missing the part where now I'm confused as to how the others okay you go away I'm now confused as to how this ever worked so now I'm confused as to how fruit is unselecting yeah because we're not hitting why is selection mode going into single ah because I I intentionally toggled it up in my Constructor up here just as a way of quickly testing it yeah I've the multiples seem to be working fine but now I'm curious why I can't because multiple is easy it just untoggles which is great single is supposed to be a single item selection and it's working the way I would expect at the if all we consider is top level it works just fine for some reason uh it's because they're different lists they're different lists under the hood that's why it's getting through because it's not like there's a shared items host for all of these the because each of these items are contained within their parent now I'm surprised well I guess I'm not that surprised these items wouldn't unselect because they are just like if we Snoop these guys okay this kind of makes sense because these guys here are just inside of a virtualizing stack panel but this is a items panel there's no actual uh parenting which is like what this guy is set up with that is expected Behavior at the moment I think yeah I think that's expected Behavior at the moment okay I am going to um I'm going to commit what I have for the moment I'm going to push this uh yeah we can put on the main repo sure and then I will probably Circle back to this like I said I need this for a project at work so we'll see we might even get time allocated to work on it outside of normal times when I have to work on things so I might want to dig in a little more on how the tree view here deals with its selection because the on Mouse button down here this guy here what was the selection on selected Tree View item that's all fine wasn't there a thought I saw a minute ago the on click at doing something interesting yeah this select get item tree change selection so it's doing something more interesting and I suspect we might need to have a merge of the two things together here if selected all right so it goes through this grabs the old one out of here and I suspect specifically so that it can come in and do yeah selection changed and it's toggling the selection because and this is the part where Tree View only supports a single selection I wonder how complicated because it's really list boxes driving the selection um because I wonder what it takes to do to have this thing keep track of them because at the end of the day I want the parent level control deriving all of this even though they're contained within a child and it might just be a matter of having it iterate make single selection select just this item yeah because they've got this selection changer and this guy here how do you know your items how do you know your items uh owner update blah blah to select to unselect yeah so I'm curious to understand how it keeps track of these ones ah it's going after the selected items here inside of selector ah you dirty dirty dog so I would need it to end up in there interesting interesting interesting that is very very interesting I am also wondering if it would make more sense because right now you can see how this is one big item I'm I'm curious let's go back real quick I know I really need to end my stream because I'm I'm tired and fading but uh uh test Explorer did they how did they go about this when Microsoft built this out did they did they put everything in one big list or is it nested there's a top level item in here so this View ah so they are adding and removing to this collection and that's what I was wondering about rather than having these things be actually in a tree View and that'll probably take a little work to deal with the hierarchical data template because that template is very much designed and being driven by the idea of children are contained within their parents where in this case the children aren't contained within their parents because him and him again a tree View this row here is contained within this one but in this list view layout this list view they are set there and if I flatten them into the same list that makes my life significantly easier that makes my life significantly easier specifically from a management side of things because then all the selection stuff just dies and the list you can handle it I think that's the the path to go down is rather than embedding them one after the other change it up so that they are straight list items and then they must do so 20 must disappear when I do this yeah it's just foreign no that's not the I want the visual Studio One so it's 20 this visual so they just collapse the visibility on it interesting interesting interesting and then if I expand you again are you a different instance what's going on what's going on here I Collapse you then go here still on the list it's interesting I guess there's no reason for the garbage collector to clean it up yet unless Snoop is holding on to it ah I bet you Snoop was just holding on to it and it was being virtualized out because these are inside of a virtualizing stack panel I was sort of expecting the item to just disappear out of it but I think that will be the trick is to switch those in and because it's our own control based on list View we were gonna have to implement the hierarchical data template to begin with but if we flatten it that solves the problem okay I will have to think on that I will think on that okay well thank you everyone for coming in hanging out appreciate all the new people coming in love the jokes love the chat um I do apologize for the um the one that I had mentioned earlier about wanting to get there was a question that came up on Twitter about managing multiple windows inside of mvvm and the proper way of managing it and I had made a comment that I was going to go through and address it on my stream and I grossly underestimated how sidetracked I was going to get um just to give a quick answer on that regard the the easiest way I've I've come up uh around doing it and it really depends on how you need multi-window to work inside of your application because there isn't one right answer um in a lot of the cases that I do I usually have one main window that drives most the content but usually there's like an about screen maybe a licenses dialogue those types of things that come up and oftentimes I will create like an i window manager and I dialogue manager or similar things and hide away the the creation and showing of the window inside of there that way my view models can take a dependency on the interface rather than having to do something direct the other option depending on what your windowing strategy is you could go with a pub sub approach as well so for what it is worth um but yeah um I think with that I am going to sign off for the night those of you who I work with I will see you in the morning uh everyone else see you next time as always happy coding
Info
Channel: Kevin Bost
Views: 1,398
Rating: undefined out of 5
Keywords: programming, C#, WPF
Id: H1JjqzZzdz0
Channel Id: undefined
Length: 198min 4sec (11884 seconds)
Published: Sun Sep 03 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.