Live Coding in C# - Principal Software Engineering Manager at Microsoft
Y'all want more live coding 🤨
Join me on Tuesday morning at 7:00 am PST for some C# fun! As always, AMA style so you can ask away as I'm coding.
What do you want to see live-streamed?
View Transcript
get on the platforms one sec the chat I have things out of order hopefully we can see the chat now I got a different angle today unfortunately um literally a couple of minutes before going on stream here uh is my stream Frozen no it's back okay sorry the restream just froze for me so the feed I was getting was completely locked up um yeah I had my my camera completely failed on me right before starting this so very unfortunate uh I'm using very fortunate thing is I got this backup camera a couple weeks ago when I noticed my own camera started having some weird issues was like overheating or something but last night on the live stream my autofocus went which is really crappy um and then this morning Not only was the autofocus not working but it just wouldn't focus at all and when
I sat down at my desk it was just like blur and I couldn't do anything to change it so I'm going to have to to call a friend see what's up um but I have this other little backup camera I just don't have it mounted on the arm and stuff to swing out so it's in a weird spot but I don't know maybe maybe this will be the new Norm for streams but the problem is I'm in the middle of filming a course and I don't have my camera to do to do all the good things so we'll see I have to go figure that out but anyway today's stream will be coding in WPF and C um I figured today a fun exercise would be trying to build uh I guess what we call like a wizard which sounds kind of funny to say
out loud but um in user interfaces when we talk about wizards they like you can probably think about most installers that you click through those would be a wizard um you know you have some type of like back next uh go to start cancel kind of like buttons usually at the bottom or something you have different screens that you're stepping through so these are like the in general called Wizards and it's funny because I spent a lot of time building Wizards before and it's been a very long time so I figured we would kind of struggle through that together cuz it'll be kind of fun um but yeah I think let me get my screen shared over here so hopefully that worked it looks like it did I am going to go ahead and run this example application that we left off with from the
previous streams so it's going to be super ugly but just to kind of show you what's going on we should have this splash screen that comes up if Visual Studio compiles come on look at the splash screen and it goes sorry I just realized too that I'm the splash screen is starting up Center screen and it doesn't have any uh doesn't have any title bar on it when it starts up so you probably miss the uh most of the splash screen but we end up getting left off with this window and what I want to do is go build a Wizard inside of this window so if you can uh conceptualize this with me for a moment the goal will be that we'll have some type of control it sits here in the middle we could do something like a little footer on that control
that we'll put some buttons onto um I think to keep this one simple we don't need custom buttons we could I don't think we'll get there today to talk about it but we could talk about having a back and next button and then we'll have steps that we can put into the wizard so that way this entire middle portion of the control will be replaced by um whatever kind of step we want to go build in the user interace face I'm just realizing the parts of my stream are lagging behind uh an incredible amount so if uh if you're noticing the video is kind of weird or anything please just let me know trying to trying to do what I can with my current setup today but that'll be the goal so we are going to need a wizard control we're going to need wizard
step controls that will go drop in these are going to be things that we can customize and then we'll talk about how we can go try and use view models as much as possible to do some bind um hello Costas from Twitter good afternoon to you it's nice and early here at 7 in the morning so so that'll be the goal I think um I want to try as much as possible to not hack things in and when I say hack I mean I would like to try using mvvm and binding and things like that as much as we can I think if you at least for me conceptually not having been in WPF for a while if we just wanted to get code working and we just want to have a functioning uh wizard like we could take a lot of shortcuts um and
I should use air quotes shortcuts because um I mean the code will work but uh in terms of like proper design patterns and things like that for for WPF I want to see if we can not break a lot of rules so um we'll start with that I think what I'm going to do as well is I'm not going to start with the splash screen because that was the goal last time but it's going to be just in my opinion pretty annoying uh so I'm going to comment this out we don't need a splash screen to launch every time we want to go play with our app but I think I did have uh what I call a presenter for the main window main window presenter um you'll notice uh you'll notice that I'm basically doing uh what I call presenters in here it's not
exactly mvvm uh I got to block this person in the chat because um I don't know why people just love spamming but see you later and we're going to go main presenter and show so this type of thing where we're using presenters uh for to if you haven't seen the previous streams or watch some videos I've been putting out on this um I have some patterns that I like to follow for WPF and I like having uh it's a a presenter is kind of like a controller for model view controller Paradigm so that's my kind of way of doing it if we jump into this one it's very trivial it just shows the main window um but the other thing that you'll notice here if we just have a quick look at this this main window presenter takes in a main window directly it would
be very cool if we could instead of interacting with the user uh user interface controls directly that we can interact with their view models so just to show the main window I'm not going to care too much but when it comes time for working with the wizard that's when I want to see if we can do a better job but anyway if we go launch this one now it should just put up the main window and it does so we can skip the splash screen for the time being and save us some effort so with that said I'm going to go make a new user control and by the way um I should add like I have an idea what I want to build but I haven't fully figured this out um so it's going to be a little bit of a struggle but I
think that's why live streams are kind of fun so wizard control naming convention I like to use um I will put control at the end of the name of a control most of the time um there are some patterns I use if I want to put an interface onto something that belongs in the user interface but I also want it to be agnostic to like to the user interface technology I will call it a view so for example if I wanted to put an interface on the wizard control which we may get to um I would have like ey wizard View and ey wizard view would not have anything that is WPF specific associated with it um if you watch more of my streams depending on how how much content I end up getting through over the next upcoming weeks and stuff that will become
more apparent because I like designing the sort of you might call it's still on the user interface but the backend code supporting the flow through the user interface my goal is that I like that to feel agnostic to which UI Tech that I'm using so if I want to switch to WPF from from WPF to Wind forms or uh I've literally talked about this before where I was building uh you know games I was building some of the backend logic and then I made the user interface in a console app like maybe not not the best thing to do but just for getting up and testing um it works really well so I like having that separation it works uh well for my experience okay so we have this wizard control um another thing you'll learn about me pretty quick is that I am terrible
at designing stuff so um one thing I like to do is I like just picking uh really bizarre colors um so that's going to be magenta maybe we'll go something a little bit less aggressive uh cyan is also aggressive but maybe less aggressive the reason I like doing this is when I'm laying stuff out I just want to see where things actually uh exist so um I'm going to go ahead and I'm going to add just a couple of rows into our grid here there's a lot of different ways that you can do this so what I want to do is have we're going to keep it pretty simple for this one I think I'm going to have a row definition at the top that's just going to be uh I do auto here I'm trying to think I want I want to have a
small footer so I might fix the size of the footer um so I might do like I don't know we'll do that so I'll have an area up top and then an area at the bottom that's the footer and then what I'm going to do is add a uh let's see do we want to do a stack panel at the bottom I'm just trying to see if co-pilot can figure out co-pilot's pretty smart look at that um look it's all done so orientation horizontal let me do this as well just so we can see it uh we don't want it to be in row one we want it to be in row sorry we don't want it in row zero we want it in row one um why isn't it showing up though there's not a lot of uh real estate on here oh missing
a thing okay so not quite we don't want that to happen uh why is that up there am I going crazy here it's in row one oh you know what um this is probably not a good way to do it it's it's basically I think it's actually making three rows here so um there we go I I'm going to try to briefly explain what I think was happening I had Auto here which means that the if we're just talking about two rows on our control um the Auto height should make it so whatever control you put inside there the row will adjust to the size of that and then I was not putting anything into it and then I set the next row to be 32 and if you think about how WPF wants to go fill up the control you're it's saying you have
nothing in here that's going to be a size of zero and then you have a size of 32 how the heck do you expect me to fill this vertically like it it's not enough it's not enough pixels so it's B it was basically putting in like an empty row it's not an actual row but it's rendering the back of the control there so we don't want that we want um if I do like one star um the asterisk here is just to say proportionally to other sections so we could break out we could do something like this you'll notice uh I'll change this back in just a sec but you can see now or it might be hard to see but this line in the middle I have row zero Row one and row two and Row one and two have an equal waiting if
we wanted to change that we could do this and you'll see that row zero is half the height of Row one now that's not what we want we just want to do this and that should be good um I don't think we necessarily need a finish this is just going to be really difficult to fit all this stuff on the screen uh there we go I'm going to get rid of finish um I think this might be a good starting point so we have a back we have a next and let me just make this a little smaller in case we want to drop back in cool that's a little bit more tolerable let me get that out of the way cuz the chat okay so we got something here and we have a back button a next button again I'm going to talk about
some of these things you might know them very well other others might not know them at all uh we have two buttons here we can see that we have a binding for the command and this is going to need to go to our view model which we have not created for this thing so that will be something we want to think about um another thing that is worth looking at is like we're going to want to talk about whether or not we can go to the next step in a wizard so that's something we have to be thinking about and who gets to make that decision is kind of an interesting conversation because uh the wizard knows whether or not there are steps before or after in theory or maybe maybe that's just a a naive way to assume but let's assume that the wizard
knows if there's a a a step or something that comes after if it's very linear let's say then then you might give a list of steps to the wizard and it knows right like if you're kind of like if you're thinking about traversing an array you know if you're at the first position you can't go back and if you're at the end you can't go forward so if we had something like that for the um for the list of steps for The Wizard and it's very linear then the wizard itself is probably the most knowledgeable however we could think about the steps in a wizard being uh not linear necessarily and each step might be responsible for saying if you press next here's where you're going if you press back here's where you're going uh or maybe back is always maintained by the wizard so
these are different Navigation Concepts you have to think about the other thing that this wizard currently when we're looking at it this way does not support is that the what's a good way to say this so we have two buttons back and next but if you wanted a step that could basically jump around and not just have only one next step but have different next steps um this wizard won't support that so the way that you need to do that is make it such that the controls that the user can interact with on this wizard uh like say for example if you had radio buttons you could have the user pick which radio button and that's going to determine the next step so when you press next based on what the select ction is so that would work but this wizard we're not going to
make support having uh different controls up in the top that steps can jump around to other steps just to clarify that okay so we can probably go look at some code um for those of you that aren't familiar commands are a built-in thing to WPF that let you go exercise some some code um it's more complicated than just a method call but the way that I'd like you to think about this is kind of for now kind of like an event handler so when someone clicks the button this is the command we're going to go run but we can go see how we make a view model so we get all this bloat to start with we'll get rid of that um I'm going to be using dependency injection for as much as I can so kind of funny like I just I don't know
if co-pilot's listening to me but there we go um by the way that's a funny thing I don't know if you observed but my co-pilot has been broken forever I'm going to repeat what I just did see how it's nice and beautifully uh vertically stacked watch what happens when I complete like no one asked for that no one no one said go and Dent all this stuff in the most ridiculous way so I joke that most of my time now when I'm coding is is is basically just deleting whites space I can't stand it um I love co-pilot but whatever that formatting is is nuts um okay I first of all I don't think I want but why yeah exactly I don't think that these are the things that I I necessarily want in here so as much as co-pilot's usually helpful this is not
going to be it for us and I do want to use a class and not necessarily a record for this because it's going to be as much as we like I like view models just being like a a data transfer object usually they're something that you consider observable so they can have state change and that's how we can make bindings work so um if we're thinking about what we have in the UI right now we're going to have to put some commands onto this so we'll get to that in a second this is usually how I like to do dependency injection with view models I will put a data context here like that and you can't make this control unless you give it a view model um if you are comfortable using WPF you'll know like hey Nick like data context is assignable from the
outside like we can call line 13 something like this from outside of this control and I know that but I try not to just my coding style is to try and use dependency injection because I use dependency injection in all other walks of programming and I don't know why WPF has to feel like it's not designed for that but um no co-pilot you're getting too aggressive so the couple of things that we have already we have an I command and what do we call them back in next command and we'll do next command so these are two things that we'll be able to bind to and just to kind of show that they work we're going to try something out here I don't know I feel like on SEC we'll make a Constructor for this guy co-pilot is just trying to get a little bit
too ansy about completions here I don't think it's built in but there's something called a relay command and I don't know where it comes from but it must exist somewhere because I don't think I invented that name but it's been a long time so a relay command from my perspective is something that looks like this uh well co-pilot there we go so clearly clearly it exists somewhere because co-pilot just figured it out um it's a nullability sure but see look at this silly indentation like why does it do it that's so annoying um what else is going on here we don't want that to be null this here oh this event handler I'm just looking at the warnings that it's kind of complaining about here so can execute can take in a null why is that oh up here okay most of the way there
we're getting there we're getting there these are just null ability um because I don't have warnings as errors like it wouldn't actually break anything but um I don't like that being public but yeah that's kind of weird I don't like a I don't like people on the outside being able to raise events on things but I just kind of used whatever co-pilot dropped in here so the point that I wanted to work through is that the relay command lets us have a delegate so we can go do something like this and we can do the same thing for the next command and just to show that it's working and why isn't it happy because once a par parameter passed in not no parameter okay so if we have this we set the data context up here we should in theory based on our bindings Mac
command next command on the data context if we jump back over here back command next command these should work we have to get our uh wizard dropped onto the main window um I talked about this other thing before that was called like view stitching it's this concept where I put controls I basically build the user interface in code I'm going to just cheat for now because it's not really going to be conducive I feel like to uh what we want to do here so let me get rid of this um let's just get rid of some of this other stuff too I'm going to use wizard control here here no not that where's our wizard control you want me to build first maybe one sec that's funny uh the name space okay so it's going to be in what's probably called the local name space
for us on the main window right so this here the name space is local I just copied and pasted the namespace to make sure it's the exact same one so we should be able to say why can't it see that that's so weird oh yeah duh okay so it doesn't like it it's not showing it literally because of this it needs to be a parameterless Constructor we're breaking the WPF rules too bad um so the designer is like no I can't I can't do that like that's not allowed that's not allowed so unfortunately when we start doing this it breaks things but that's why I like doing my my code behind the scenes so let's go run this no why where's my exception window okay I have three monitors the first one the one that I'm on is 48 in and then I have two
30in monitors beside that it put the exception dialogue in the far corner of this other screen so let me go break my neck object reference not set to an instance of an object and yeah that actually makes sense like I just realized even though I want to go cheat and on the main window drop this thing in it it actually won't work and that's because it doesn't know how to go construct this so we need to use dependency injection so that's okay uh I'm going to use a Content control here and just to kind of prove it how big it is uh for sizing see like that's helpful and this is why I do this so I'll walk through it again I put this content control on and I'm like hey look I can see the main window that looks good can we see the
content control like I don't know because there's no content in it but how big is the content control if I assign a background color that's ridiculously aggressive against white notice how we still don't see the content control can we do this no we can't so I'm hopeful that when we go drop in content that it's going to take the size of it but it's been a long time for me so to make our view stitching work which I'll walk through in just a moment we need to give this a name call it wizard content and then when we go to the main window this is where I'm going to have to pass in some other stuff and I commented out that code didn't I sorry for jumping around so much here this is just from the other streams I had some other code and I
moved it all over to here there we go so Stitcher Factory hello rambling geek good to see you back okay so Stitcher Factory that's the thing I want from dependency injection what we're going to do is ask the stitcher Factory to create a Stitcher um oh you know what I didn't build this on stream I built it for something else uh we'll make we'll keep going I'm going to have to go build this part but we're going to ask the um wizard content and we're going to take in the Wizard control okay what this is doing or what it will do so this is a facade it's a design pattern I'm basically creating the API that I want to use and we have to go Implement on mobile stream is spotty well hopefully it's probably not just you I'm My Stream setup seems like it's
kind of glitchy today I don't know I hope my audio is coming through okay but I'm watching on even on uh restream it looks like my video is kind of choppy I don't know if that's other people's experience locally it looks totally fine uh I'm watching my Tik Tok window record my obs window that also looks totally fine so everything local is okay um I I just don't know if uh if everything is okay but we'll see this Stitcher Factory like I said is a facade so we have to go make the complexity behind the scenes oh YouTube stream is good thank you for letting me know I appreciate that I don't you're helping reduce my anxiety because let me tell you the first few minutes before getting on here I'm like looking at the time I'm like okay I got 15 minutes I sat
down and then it was like uh depending on when you join the stream right it's like I sat down and my autofocus from last night was just busted so I'm like okay great I don't have autofocus and then I tried manually adjusting it won't adjusted and then after that I was playing around with some settings then I couldn't even get the video feed from my normal camera to go to my computer so this is the backup camera um I kind of like this is a neat little Vibe but I I want to make sure sure that I can thanks uh on LinkedIn to I appreciate that I'll stop panicking but yeah I got to figure out what I'm going to do with this other camera because uh I'm making more Dome train courses partway through and if it looks consistent then I will use this
camera but I I'm kind of hesitant about that I don't want to have a course experience where people like partway through it's already one thing where I'm getting haircuts or my beards growing out and changing clothes in a course but it's going to be kind of jarring if someone's like this is just a different camera like it's very obvious so we'll see let's go make this simple Stitcher though um I'll explain how this is going to work so public interface uh there we go co-pilot knows so the stitcher when we go to call this this these are just the parameters we're going to want to pass in when we go to stitch and for a simple one we don't want anything the grid one which we built before on stream this one is going to have a row and column you could also do like
row row span and column span on that but now we have to go make a Stitcher let's see if co-pilot figures it out so this is super cool um this is I say this is super cool because this is a concept like I came up with this and when I say I came up with it maybe I'm not saying I'm the first person to ever do this but no one taught me this this is something that I came up with on my own um and the fact fact that co-pilot has an idea for what I would like to do is kind of interesting um it's not quite what I want though so I want to make a simple Stitcher but I want it to be a uh specifically for a Content control so I don't when I build these I don't like to do this
kind of thing I like building stitchers that are more dedicated because we have to go wire this up uh alternatively so what I'm going to do is we have to require a Content control call it a simple content Stitcher this is really the magic that line so we'll just take that and it is parent that's all we're doing very simple and now we need to go wire this up or else it won't work and that's where I had all this code up here we're going to have to call this so let's call it something different um stitching sorry I renamed all this stuff CU When I was making YouTube videos I didn't want to lose the code because I figured we'd need it on a stream but then I just kind of hacked it up here so um static void we want Stitcher Factory we'll
get rid of all this other stuff it's apparently still very early for me um and we will do this so when I it's kind of funny for if you're not aware a lot of the time when I'm streaming stuff or making YouTube videos it's because there's some type of relation to other stuff I'm doing outside of uh outside of just YouTube and one thing when I went to go take the stitcher code that we built on the previous stream something else that's missing from this that I like to have is the type of Stitcher that's being requested and then we can do some more uh like more appropriate filtering that's funny my camera's gone uh this is what happens when you're not prepared Nick sorry folks my camera needs to be plugged in so one sec there was I didn't realize my the cable that
I plugged in was an uh was an HDMI cable only I thought it was a USB cable that it was doing everything over so uh the battery just died which is funny oh and I don't have a good uh USB here man that's annoying what a morning this is okay let's let's keep going I might just go headless for now this is going to be too much of a disaster to try and do let me turn off my face sorry about that that's very disappointing I mean you don't need to see my face it's not that exciting okay so we we go make this Stitcher registration it knows how to go select the stitcher this is like nasty complex code that's why we put it behind the scenes of our facade it gives us a nice API and we have all the gross stuff behind
the door so now we got that what I'm going to do is make sure that we call this stuff so we have to make sure that's called at the beginning here so I'm going to do service collection add Singleton and what did I call it stitching oh I didn't make it static but whatever let's do that stitching dependencies and I didn't make the method static I did it's just private there we go so this is going to add into our dependency container that Stitcher and I can take a deep breath okay so we have the stitcher added to the dependency container here great if we jump back to the main window that means that the stitcher Factory should be able to get past in um I'm using something called screw Tor and it should automatically wire up public classes so the wizard control should be
able to get passed in but to make a wizard control I jump over to here to make a wizard control we need to make a view model for it and to do that screw door will also pick this up because it's public so in the this should all work we get this simple Stitcher let's go try it out looks like we got a wizard on the screen very nice so that seemed like it was a lot of work just to drop a control on here but I want to back up for a second so I was missing some pieces to go uh wire up the user interface so we had to go build that so that took a little bit of time but really this is like if we had that thing already right on Youtube yay yes exactly so uh yay it's working so
this is really all we need to do to go wire stuff up in the user interface now so um again why do I like doing that sorry I don't want the wizard control I like making sure that I can have dependency in ction working so if you are watching this and you know a way that I can easily still use zaml and drop in controls that do not require public parameterless Constructors let me know uh because all of my coding efforts have led me down this path where I passed them in because I want dependency injection and then I came up with my own pattern to go why are these things up but okay what we didn't test the most important part of our wizard was did our bindings work and off screen next works again offscreen back works so we do have these functioning
buttons I mean functioning in the sense that we can control some of the interactions but we're not navigating or anything yet so this is where stuff's going to get a little bit more difficult okay back to the code we go let me get rid of some of this stuff too that's too much noise too much noise to look at so we don't need to go on the main window anymore we don't have to look at stitching hopefully anymore uh Splash Window we'll get rid of that okay so we got this view model now there's a couple of different ways that we can go make this wizard control work so up top here we should probably go put a Content control in nice it's like Nick likes really bright colors let me go do that um we don't need that uh necessarily but we'll put this
content control in here because this is where we need to have the wizard step I going to call it wizard step content the idea here is that as we're on different steps what we want to be able to do is make sure that we can switch out the control that we're looking at so this content control its content property will get changed one way that we can do this and I think there's some nice benefits to this and other parts I'm like it's kind of gross so let me explain the content property on the content control is something we can bind with so we could say we could go do this right now here's where it gets a little bit weird if we want to go have this current wizard step view on The View model that means that our view model needs to start
having like I like this is why it's weird for me I like having my view models be very uh WPF uh ignorant I guess I don't like having any type of UI thing on here even I command I really don't like this because this comes from system Windows input I command like why why is this in system Windows input like why can't I just have something that I can bind to that's not from there I don't like it but we can do this kind of thing um UI element I guess and we're going to come back and fix this up but just to prove that the binding is working right let's go just kind of make this hacked up a little bit current wizard step view let's just go put a new panel um how do we want to do this new panel can I
not do that what's it complaining about oh a panel's abstract okay uh a new dock panel and and background color light gray is not good enough we need what's a good color purple it's funny because if you are ever to watch me develop user interfaces kind of like you're doing now this is literally how I do it I just pick ridiculous colors and then I go through and clean them up but it tells me the sizing so I wanted to do this so that we could see if our binding is working and it is so now we know we have a next and back button that we can go wire up functionality to we know if we set this current wizard step view as long as we're giving it a control it will go put the right thing into here which is kind of cool
right so that's all very interesting now here's where things get a little bit more weird is that I don't want to have the well let's talk about let me back up we have bindings right so these things are are bound to our user interface but one thing that's missing if we want to do this like we have right here it's only working right now because I set it up top before initialized component so by the time we come into here I've already set the current wizard step view on the data context it's some Doc panel so on line 12 it's already set then we set the data context and when we do initialize component when it sets up all of the bindings it's going hey what's your current wizard step View and it goes hey here's a panel that I have already it's like great
thank you so much but now if anyone after this comes and changes it The Binding doesn't know to update and that's because we need this thing and there's no base classes there uh okay we need I notify property changed and I haven't checked because it's been ages but I could have sworn that someone came up with some code Generation stuff with some fancy attributes that made this way nicer so if you are watching this stream live and you're like Nick why aren't you using all of the fancy code generation things please tell me because what we're about to see is why this is so gross so to make notifi property changed work we have an event then we have this method that we use to invoke that event and it's all co-pilots out of date here caller member name and this this is I think
the actual signature that we want and that's because when we go call it from a property we can ignore passing this in and uh the compiler knows that when you omit this from the call site when that's not provided it goes oh I know you wanted to pass in the caller member name and and that's perfect when we want to start talking about properties in particular so my uh it's funny my oh you know what it is I think the Tik Tock live studio is stealing my ALT key um there's a refactoring menu that I'm trying to do and it's Alt Enter and it's not coming up wow nothing okay I wanted to do convert to full property see how long that took that's why I was just trying to press Alt Enter to get it happening but um the thing that we want to
do is this essentially so I want to say if that's really it right so if it's changing then say notify property changed and that way just to kind of prove a point just to prove a point after the fact if I say view model thought sorry I didn't need to copy all of that what's a nice color lime [Laughter] green right lime green we love lime green there we go um what's this complaining about ah must be nullable technically okay let's go run this thing so we should see that the binding works even after initialized component and it does right so we're in good shape here because if we start changing that current wizard step State it's going to reflect in the user interface it wasn't just on Startup of this control okay so obviously we don't want that here because it's hideous um we
are in a position where we can set this that's very nice uh what else well I think it might be time to start talking about our presenter I'm going to leave this in for now let me put a fix me here um because I just want to make sure if we're not at a spot yet where we can see things changing in the user interface I just want to make sure that we don't break this Behavior just for now um but I got to come back and remove it because obviously we don't want that there permanently okay so presenters two new lines let's get going here so public sealed CL CL uh Wizard and here is where everything breaks down for me I'm not exactly sure how I want this to work yet ideally with the wizard presenter uh what I would like to be
able to do is I want to operate on The View model itself and this is a good moment to pause and talk about this for a second this wizard control that I'm making the way that I'm about to do this is that this is one single wizard control for the entire application so if you wanted a reusable control the way that I'm doing dependency injection and stuff you might want to reconsider because what I'm going to show you here is that this thing needs to take in uh not the wizard control wizard control view model okay so it's going to take that in I'm going to make a Constructor for it because I'm wiring all of this up through dependency injection what's going to happen is that I'm going to ask to resolve this thing here okay so I'll ask to resolve a wizard presenter
it's going to say great I'm registered but I need a wizard control view model to continue like I can't be created without this now you'll notice that when I double click on this visual studi is highlighting all the places that that text exists and the other place in particular is up here so this is going to be a single reference off of the dependency container it's just the way that I have it set up so if I go resolve a presenter and I go resolve a wizard control we will get the same view model instance now the way that you work around this is that if you don't want that you can either change how you're registering dependencies which is probably what I recommend for most people but because I'm using screw door if I go back all the way to the beginning here this
little bit right here is explaining hopefully why that behavior is going to happen so with screw door I'm just scanning and pulling in everything anything that's a class I'm saying I want you as self and with your interfaces and you're all Singletons is that good not necessarily this is just how I started building this thing and I'm just calling out that why this behavior is going to happen you can still work around this with that Singleton Behavior if you're like hey well Nick I want to have a wizard in multiple spots that's totally fine it just means that you have to go create your own instance of the wizard control and wizard presenter you need to own the lifetime and the creation of that if you ask for it from the dependency container the way that I have it set up you're not going to
be in good shape because it's going to share the same instance just a heads up okay now that we have that we have to think about what things we want on our presenter and the way that I like to think about this is that this is like how we would control uh the flow like it's almost the business Logic for the user interface so like what is the user experience that we want and something that I think would be helpful is if we wanted to say hey look uh I want to uh we we probably need like an initial step so that's kind of an edge case is like what's the initial step but if we wanted to say go to step right um we have to talk about what we want here okay so we want to go to step how do we make
this happen because there's a couple weird things going on if you think about what this presenter conceptually allowed to know about it has a view model so we should be able to say this right we should be able to set the wizard step view to something which is all great but does that mean that this only needs to know about this I don't like man there's two I hate I hate when there's like a like UI element like that I don't like that that looks gross to me but anyway there it is so is that all we need to do like almost like it almost kind of works for us right and let's maybe kind of back this code up a little bit I'm going to call this from the uh the main window presenter we don't need this Boolean converter get rid of that
actually sorry that's for that's for another video coming up spoiler alert someone on Twitter showed me that we can have value converters where we don't have to have them in the resource dictionary and we can use this markup extension thing super cool so I'm saving that that's another video coming out okay uh main window presenter where was that where I know I had it here we go where are you oh it's in a weird spot okay so if I wanted to show the main window something else that I might do here is I would say well hey you know what I want to have this wizard presenter also passed in and after we show the main window and look at that co-pilot nose so I'm going to go back to our view model here and take this Cod we're just moving where it's happening okay
so there should only be one spot in all of the code now that's doing this purple background to prove it there you go only one spot in all the code Okay so we've just changed where this is happening if I go run this now we get purple so we know that we can use our presenter to change the step lovely okay cool stuff but what now because these buttons when you press them we need to be able to navigate between steps okay so this is where for me I'm going to start losing a bit of confidence in how I want to go design this because I haven't done this next part in a very long long time so I'm probably going to Fumble a little bit more than usual here so please bear with me but this part in my opinion is not what we
want and I think what we want is uh interface uh I wizard step view so we want something like this and I think if we do this kind of thing the reason that I want to do this well first of all that's not going to work it's not a UI element but I want to do something like this because we need some type of API that we can work with because I'm going to have to uh listen to changes on the step itself so if the step like when we ask to go next so first of all we need to the step to tell us is it okay to go to the next step like maybe has to do form validation or something right you need to select a couple of options before you can even go to the next step if you're imagining a
wizard so uh if we're on on our Wizard and there's some controls here like if you haven't entered your username or something should you be able to press next like the step itself knows that or it should have some knowledge about it so how do we make sure that we can ask the current step for that kind of information that's what we're after here so we need some type of interface to work with and I think the the problem I'm struggling with right now is like I don't think that I need it to be a view necessarily like this part needs a view that part is going to be the actual user interface setup but I also need some backend information so um all all of our controls have a data context on them right so what we might do is this and let me
explain why I don't think this is a stretch so conceptually every wizard step view is just some user control that we want every user control has a public data context on it already it's actually of type object which is pretty gross but that's how it works so every control has a public data context on it and all that I'm saying is every wizard step view needs to have a public data context essentially but I'm I'm strongly typing mine so I don't think that this is a stretch personally I think that might be okay and if we do that then we know that this wizard step view we can have a view model that we can access on it so I should be able to do wizard step view get the view model blah blah blah after that so that's good this part's kind of busted
that's okay because I think if we do this kind of thing and we just change it it just works now you might say well Nick how the heck is that going to work you're saying you can take any any silly thing that meets this interface and put it in the UI and I'm like yeah kind of uh and it's going to work for now we'll talk about how we can break it pretty easily it's going to work for now because I'm going to make sure that anytime I make one of these it is just a user control but there's nothing stopping us from making it something that cannot actually be assigned to a Content property on a Content control if we wanted to really prevent that my opinion is that we move away from The Binding and we use a Stitcher again and just have
more control because as soon soon as you're using object as a type you get into some really weird places so this part is broken now that's what I wanted to find it's broken because it's not actually a wizard step that's okay so we're going to make a new Wizard step so we need a new control our first we'll call it our first wizard step and of course we're going to make it purple we'll keep the purple theme going so we got this wizard step that's purple it's beautiful and from here we're not going to add much we're just going to make sure that it meets the interface okay so this is the code if I could double click it thank you very much I don't I know why they put all those usings in there it's disgusting okay so it's a user control but we
need I wizard step View and to make one of these we also need to expose that we have this view model available uh I'm going to cheat a little bit here okay just please bear with me so I'm going to make a and actually trying to think how I want to do this so if we have multip this I'm just thinking about the dependency injection part I'm trying to get a little bit ahead if we only have one reusable wizard step view model like it's just made to be very generic the way that dependency injection is going to work is that if we resolve this wizard step and actually I broke my rule that should say wizard uh our first wizard step control but anyway um if we use dependency injection to resolve this and I pass this in very much like this right if
I do this kind of thing and this is just a very generic wizard step view model if we go make our second step and it has the same class here it's going to use the same instance just based on how I've done dependency injection because it is marked as a Singleton so that's something to think about um if we want to have a reusable one like we need to make new instances of this we'll have to think about how we actually go create instances of the the step itself um so this might be something where I I don't like using Bas classes a lot but I might do a Bas class here we'll worry about this when we start putting in our second step though I'm just calling it out as something uh you know especially if you're you're watching this and it's recorded you
don't have an opportunity to ask questions I just want to make that kind of clear so we're going to have this view model here and needs to meet this interface what did we put on here nothing yet excellent and we can do this apparently not oops my bad there we go okay so all is good now if we go back to here um okay so here if we don't want to use dependency injection right if you don't want to there we go so that's no dependency injection this is kind of weird to do um I I'm assuming if we were building up more complex wizard steps we'd want some type of dependency injection and that means that we'd have to be able to pass that in or we would say from here um so we could do this kind of just like keep moving the
responsibility back out like should should the window presenter know what the first step is like maybe not but that will mean that whoever is calling it is is going to have to be responsible for figuring it out so let me go back I forgot that's the splash screen code actually let me put that back I'm just going to comment at all the splash screen stuff I missed there we go okay so we still have to go do this part though so you might say okay well not what I wanted had the wrong stuff on my clipboard uh new our first wizard step new right so I'm not using dependency injection again here but what's really cool as you'll notice I have the service provider right there so if I wanted to okay so I can do it either way and we're going to start with
the dependency injection way because when we go to make our next step I want to show you that our view model is probably going to get clobbered I think it's just a good exercise to think through this so if I go run this now like I said we only got the one spot that has purple fingers crossed we'll see if Nick messed up but not today okay so probably looks pretty Bor boring because I've been running this repeatedly and we keep just having this purple rectangle but we are getting further right and we're getting further because we've now built a presenter let's close that let's close that we're building this presenter that's able to take in the step that we want to be at so now we can start to control this a little bit more um so what do we want to do from
here well I think the wizard step view model is going to need to have some information on it about whether or not we can go to the next step so we'll have to figure that out um and it's going to be a little bit weird because we have to use this presenter to kind of Link the two different view models that we have going on and what I mean by that we have this wizard control view model right this thing had oh that's not what I wanted sorry this thing had the back command the next command we probably need something that says whether or not it can go back or can go next right so if we go back into this view model there's a couple more dependency Properties or these aren't dependency properties sorry just bindable properties come on co-pilot no so lazy uh
let's see okay let's see copile let's try again thank you very much thank you very much okay so if I go put these as bindings Now by default they're going to be false but that's okay so we will say is enabled can't go back we'll do the same down here but for for next okay so if I go run this we should see that these two buttons are disabled now and they are I can't click them so The Binding is working because the default for the Boolean properties is going to be false so that's great and that also means that if we wanted to we can go wire up like new new values for these right so we got can go back can go next if you're wondering like this is what I was asking earlier I think that there is some uh code generation
attribute we can use to not have to do this gross like just to have a a property like this is like how many lines is that it's like 11 lines long or 12 lines long yeah and you know times two time three it's all the exact same plus you have to go declare these up here I think that there's code generation attributes we can use for that stuff but anyway okay so where are we headed with this well now we have those to be able to touch on our presenter I'm scrolling around here because it's too small of a window for me to work with but what we can do is we can change that now on our view model like we can say can go next here I don't think this is what we want to do but if we have a look right
that button's now enabled I can press it so let's think about this we have this wizard that was weird was a weird Visual Studio glitch it like oh it popped it out that's not what I asked for okay um we have this wizard when we put like let's think about the base case here so it's empty and I say hey look here's a step that I want you to go to how do we know if the back or the next buttons should be enabled well the next one I might say I want to ask the step itself like can you go next because if you can if you put a step in here and you can already go next great like that's awesome uh let's make that button enabled if not because you have to you know input some things here cuz maybe you have
a screen in your wizard that's just text that you read through right so you can just go next it doesn't matter maybe this just informational or you might be in a position where you don't have like the users input and you can't go forward yet so you need that to be disabled so how do we do that well if we go back over to here right we said go to step we do have on our view model can go back and can go next I'm going to start with can go next but really I need to ask the view model of the step if it can go next so this is going to be a bit of a pain in the butt and a bunch of copying and pasting but we need can go next on The View model this is just easier generate read
only property yeah nice okay so that's cool is it implemented though no it's not so let's go copy and paste this one okay so we have this Cano next and this also needs to be I notify property changed please someone save us with the code generation for this thing right there's the event for it all of this just to have a observable property change and then we need the method co-pilot got it right this time there we go so if we want to see if this works just to fake it we'll set it to true for now okay and you'll notice and hopefully it's obvious but I'm doing this incrementally so that you can see like where if I just showed you a bunch of code at the end well first of all I don't even know how to do it so I'm building it
on the fly but if I just showed you the answer you might not understand like which things are having an impact so that's why I'm trying to spend a little bit more time going through these details so we're now going to be asking our r view model instead of assigning it on the outside right so when we go to a step we want to say hey the step that you just gave me like let's go update these things and something to keep in mind is this is a one-time thing because what happens when that changes right so yay it worked right I can press it it's all functional but what happens if and we should maybe talk about this like if we had a step so we go back to our first step nice beautiful purple box here so if we needed a user to
check a box a very simple thing right you know here's a a license agreement you have to go read you need to go check this box before you can proceed so by default we like the initial State can go next would be false which I think makes sense but when they check that box we need to up dat our steps can go next value to true but that needs to propagate it needs to propagate to the wizard step uh sorry to the wizard view model so it's like two layers right and once we do that then it should work something else we might be able to do and this is maybe a little bit interesting I don't I don't think I'm going to do it the way that I'm about to explain to you but I just wanted to to talk about about it so
something we could do is we could change this is enable binding we could go handle this like directly in the view model so a couple I'm kind of jumping to a couple different thoughts here one option is that we could have a value converter that knows how to go look at the current step and The Wizard step I said that wrong the current step and The Wizard itself because maybe the wizard needs to offer information about going next or not so we could do a converter that could look at both of those properties that might be kind of gnarly um we could go make it so that the wizard control view model it has this right like we could and hear me out here because this is a little bizarre um you could when you go add a new one we'd have to go unhook
these but and you'd have to do a null check but just bear with me for a second we could do this something like this I wouldn't necessarily do it this way um and can go next could also be a combination of like uh we have to go check but anyway this might be something we could do let's let's just experiment because it might be kind of fun to see what happens uh so couple things we need to do a null check and then we have to do this as well and I'm going to say right so if we did this and this technically supports any property we could go say if e dot come on co-pilot you're making me actually write code um oh we didn't put Kango back on there yet but let's just do this for now we could do something like this
kind of gross for a couple of reasons one one is that we need to do this pattern you need to make sure that especially and this is just in general if you're hooking up events to things you need to understand the lifetime of those because if you're ever changing this out if you forget to unhook things you'll have either either memory leaks Andor uh really weird Behavior where stuff is just breaking and you're like well how did that happen because there's a lingering event handler still triggering stuff for you or duplicated Behavior tripled up because you you've added on the same event handler multiple times so there's something to think about but this might be interesting to try and that will mean that if we change this after it's been created then uh our our wizard should be able to toggle and we can try
pretty quick I think so if we put a check box in here oh what was co-pilot going to recommend come on co-pilot let's see it maybe some more bright colors there's no way that it heard me talk about that's not what it is anyway though but so on the wizard step view model it's can mode is uh one way to Source it's a right only thing for us and that text is way too small okay let's see if this works it's probably something I missed along the way here so that next button is currently disabled that's me clicking it a bunch of times but if I press this checkbox it's enabled now if I uncheck it it's disabled so what we've done is we've delegated all of the work about knowing if we can go next to our step so if you need to agree
to the terms and conditions before you go on I pressed it press next and we get we haven't done the navigation part that's coming up so this is like I it's a little gross but that actually might work it might be good enough to keep going um the other way that I was thinking about doing this was basically a similar idea except not having this view model understand it because the one of the things I don't like about this aside from just this event hookup which wouldn't go away in the alternative solution but one of the things I really don't like is that this is just more and more logic inside of the view model now it's kind of interesting because you might argue like this thing knows that its state is based off of some nested uh you know wizard step State like I
could I could get behind that but really all that I was going to do was take this kind of code and wherever our presenter is I was just going to wire it up here if I'm being honest with you so I think it's in one spot or the other but those are the only two solutions I have right off the top of my head so let's keep going with that we need a back button so let's get this part part put in it's all basically the same so we got that now we got to make this thing actually I bet you if I just do this I name it properly then co-pilot will figure it out thank you co-pilot okay so again just seeing if anything breaks don't expect it to excellent okay so that's good uh did I I can't remember if I did
this or not but on The View model I did put this in okay good okay and what's interesting about this too I'm just double checking this saying at the property change it's actually doing a null check on this I was wondering what this was but I think that's probably some potentially impossible State probably um another thing you could do is this so this just makes the code oh what did I mess that up why doesn't it like that oh so the goal here was just to make this look a little bit nicer we know that the person who's sending the events is going to be the view model so we don't have to go like reach outside of this event handler we can just take whatever the sender is because we know based on how event handlers work it's always going to be a view
model that's passed in just to prove it this still works so just a little refactor there keep that clean I just realized I said cleaner cleaner from my perspective I don't like when people say something's clean because that's the most subjective thing ever okay so we have our presenter we have this here we don't need oh or do we like we might need to refresh some of the state so when we set a new step we might have to know that um the the other thing to consider is that we might want to do something like this so maybe we can handle nulls coming in here so if you just wanted to clear the wizard maybe maybe we don't want to worry about that for now but we need to make sure that when we go to a step we're reading in the initial State
there might be a better way for us to just read refresh all of them I think if you how does that work I'm trying to remember if you use can use onproperty changed and not provide any properties if it Cycles through them or something weird like that but anyway for now we'll just set these I think it's time for some navigation probably and let's see I think if we wanted to do that like who's responsible for that navigation we have the next command on this view model and I don't want the view model this is my personal opinion I don't want the view model itself to be responsible for doing the navigation I want the presenter to be responsible for that so the way that I like to do this is to put some event handlers onto here and I would say like uh Mac
requested next requested and these become extremely lightweight okay come on co-pilot do your thing okay so we get these set up and means that we need to have these events subscribed to who is going to subscribe to them um that's going to be our presenter now these things exist for the same life time just as a heads up so I'm not worried about um unhooking these or something oops okay and then I like putting my event handlers at the bottom so move that down okay so now we have these two event handlers I'm just trying to get some stuff moved uh a little bit more vertically to keep some real estate on the right with the chat um so what do we want to do we've said like we know that we can go next or back because the control was enabled we were allowed
to click it as a result the command executed as a result of that the event got triggered but how do we know where to go and I think what could be interesting is if we just ask the um the current oh did we not save the current step okay this is it's going to look nasty hold on though so current step view is this is that so great we have that now um technically this should never be null should never be null I would hope I'm trying to I'm trying to think maybe what we want to do is oh no not what I wanted debug dot really come on we'll take this and we'll check I don't think it should ever be null but let's just make sure for now we'll uh we'll catch ourselves if it's the case case we'll get a a break
point there basically and now if someone's pressed next what I want to be able to do is sayy hey current step view model um like give me your next screen that's what I want to do is say give me the next screen um what's interesting about this is that I don't know if it should be a property or not or a method like do we want to call it so I can figure out what the next screen is I mean I don't get me wrong I understand that uh a property is just a method but I mean from like an ergonomics perspective should it just be a property or should we basically suggest that we expect that you have to go calculate the next step and I might do that so I might say something like that and then and then we would do this
go to step Next Step view so we got to go build this so I like doing this kind of thought process because it helps me think about how I want to call it and I might bounce back and forth a little bit where I'm like hey this it feels pretty good but I haven't implemented the other side of it so if I go to do that I'm like man that that absolutely sucks then yeah I got to I got to change things up so we'll do that I have this can or this Get Next Step thing that we're going to call that means I need to go to the wizard step view model where was that defined up here and this will be a i wizard step view now I'm just thinking about this again I like to be trying to get one step ahead
but what about going back like should this thing no I'll give you an example um usually I would say that the wizard itself should be able to track going back right like it it knows what the last step you were on so just go back but I've absolutely built Wizards before where there's like a transient step so say like a loading screen so you're on one step you press next it gives you a loading screen then that finishes you go to the next step if you're like oh crap I have to go back do you go back to the loading screen like no you need to skip back too so that becomes kind of weird and then you need to ask like again is it the responsibility of the wizard to know or should every step know where it came from and track that so
kind of a weird thing I don't even know based on the uh remaining time in this stream about 30 minutes I don't know if we're going to get there to go back so I'm going to focus on going to the next step which is fine that's okay we will put this method on here and here is our challenge so what's the next step so if we think about how we made this wizard step view model one of the things I called out was that do you want it to be generic and reused so for every wizard step you would just make an instance of this and then because you have your own instance we could go configure it that might be the case um we don't have a next step right now so there's a bunch of different options we could do here if we
use dependency injection I think we're going to be in a weird spot where this needs to be named our first wizard step view model like it's specifically dedicated to that first wizard step and then we can go customize it in here very specific but then it means that we have to go either duplicate all this code for the next wizard step view model or we abstract it and I think what I might want to do is do that abstraction so what I'm going to do is take in a value so let's see how do I want to do this uh public wizard step view model I wizard step view next step and we'll track that I will try to explain what I'm doing after I uh or I shouldn't say after as I'm getting a little bit further here but this method down here is
going to be able to return that next step so in this case it is should almost be like a property because we didn't have to do any calculations but I'm changing this now this was just the single wizard step that we had but I'm going to duplicate it the dreaded copy and paste Le and I'm going to break one of my rules I don't like doing this um but I think it's just going to help public let's do internal abstract class and I'm going to call it base wizard ST view model I don't like it I don't like it at all that's okay and the base one knows this information will make this public or protected here this is going to be abstract so someone is still responsible for implementing that by the way I should probably add context I don't like doing abstract classes
because I don't like doing inheritance a lot the problem is that if I go to make this composed these things here like the logic for them to go toggle and stuff that's all great it's shared or it's in one common spot and like a in a base or in a in a reusable class but the the tricky part is like I still have to go red declare those properties if I do that so if I just inherit I'm saving time on the on the redeclaration of any property that I want to be able to bind to so that might sound a little weird but you'll hopefully see in just a moment if I make this one our first wizard step view model we change that now called it base watch how much code I get to delete because if I used composition here I would
still have to leave these properties in and forward them but this all goes away this goes away this goes away this goes away big stupid Tech I don't know how you can just code live I freeze up well if you're watching the beginning of the stream I was messing up a ton um I freeze up a little bit but I think um you know I'll be totally transparent like I'm I'm trying to tell all of you on like as I'm going like hey look there are parts of this that I'm absolutely not confident doing right that doesn't I'm not trying to talk myself down like oh like Nick you're stupid like I don't think I'm a stupid person but it is hard to code live and it's even more difficult when you're about to do something that you're less confident in so I think what
helps me not freeze up as much is that I'm just being honest with you I'm not trying to pretend like I know like I I've said I've worked in WPF for years but it's been a while so you know I'm I'm just trying to be transparent as I go and that way uh sometimes sometimes the freezing for me happens because I'm trying not to look like an idiot but if I just tell you like yeah what I'm doing right now might be I might be a little bit of an idiot in the moment like then it helps me move along so um hopefully that helps your you're kind of thinking through things like that but oops what am I missing here less accessible okay whatever see that was me being an idiot but that's okay so you can see that to go make a new
Wizard step is actually very easy and the the fact that we have Get Next Step means if we wanted to go make a new one which weren't probably I don't think we're going to run out of time before we do it but if we had our second wizard step right you could figure out how you want to go compose this thing right and in fact if we were using a dependency injection I could literally do this and say hey look like um sorry that's not right I wanted to say our we haven't built it yet so I could do this and it would automatically get resolved so we could figure out like hey look maybe step the second one it doesn't have anything okay and then um this is the view model so can go next is true so so it's set to true and
when someone presses next it's just going to go off the edge and I should do that this should be nullable because we technically support that okay um one sec I got to go fix I got to go fix a couple of spots for the nullability let me jump back to here so can or get next step that can be null and then we called that down here I thought we said that we could make it null oh I I took it away but we're going to put it back in that's okay um right so if we put in if we say go to step and it's null we'll just have nothing to show and you can't go anywhere um that might be something you want to handle specifically like you could have like an exit condition on your presenter so you could say like if
uh wizard step view is null right that might be for you to decide so I'll just leave that there um what was I saying though we need to go make a second wizard step we're on the second one let's do it it's exciting it's not really exciting but the best part is we get to pick a new color our second our second wizard step okay chat what color do you want I'm going to pick one but it's delayed so um I'll read the chat if you pick something better I'll use it let's see what's a good color what is is a good [Music] color what's Orchid no that's too close um do we have a yellow one oh that's terrible I hate that green yellow it is but I'll see if anyone in the chat wants a different color we'll go use it so we
got to go hello Chris good to see you I am going to go put this onto here so it is a wizard step View and we all know that we have to go put this on here and our second wizard step view model which we built already um I should do this actually let me go pull this code over to here um by the way I am the kind of person that will go make separate files for everything so not that this matters I'm just sharing with you like this is when you see me streaming like this and I have a bunch of stuff in one file I'm just doing it for convenience because in my own projects I almost always will go pull these things out into separate files um it's personally hard like I use my left nav to navigate a lot and
as a result if I don't have the file names there it really throws me off um but some people like saying you know if I have this control and there's a view model like if I just keep them together it's it's easy for me and it's not for me to say right or wrong I'm just kind of sharing with you how I do things so this is kind of not what I normally do okay so we have this set up now um but we're missing this part view model I think we're there I think we're there I think what we should be able to do is we start off with the purple screen we should be able to check the box and it should take us to this next one I'm just double checking our first step is our first wizard step which is as
expected it takes in the Right View model I think we're there I think it's going to work can we go back Pro the back stuff's not going to work but I don't I don't know if we're going to have time for it let's see Moment of Truth keep in mind things never work the first time so hello on Twitch check the box okay next button enabled get ready lime green or whatever it hey it was lime green perfect okay next buttons enabled what should happen is that when I press this both of these buttons disable and we just get the cyan screen left boom it works big Wally Wiggy what we are working on is a wizard inside of WPF using C so we're trying to build a custom control that will allow us to have wizard steps so again for folks that aren't totally
familiar with the terminology in user experiences so when you're building a ux uh and I'm trying to speak in general terms here because you might call it different things in different Frameworks but if you think about like an installer or something that you have to click through with different steps the wizard is the terminology we use for that so um it's something where we have configurable steps uh each step can determine um whether or not you can go to the next step and what the next step is so again just to quickly repeat what we built so far this form pops up the it's filled with a wizard control and the top part if you see the light blue border that is a container that can hold a step for our Wizard and this is a custom step it's really big and ugly but it
has a button or sorry a checkbox that when we click it it toggles whether or not we can go to the next step so we can totally customize what allows us to go next and then we can press next and this screen doesn't have any input on it but we could go build like anything you want as long as you are setting on The View model for this you set can go next true as appropriate so what's currently missing is the back button we didn't build functionality for that um in about I don't think I might cut the stream a little bit short because I don't think in 17 minutes I'm going to get totally into a good state with this so again if we wanted to think about back buttons and why why I think there's some interesting design decisions okay so if I
were able to press back now I think probably most of us would agree that we could go back to the consent screen that we just had right the purple one so in that sense it makes it's logical to me that the parent wizard control itself could track that or the the presenter could track that and that's cool like we could build a I guess like a a q for it Q or a stack it's a stack we'd put a stack in place and we could go pop off the last part of the stack and say okay you went back here you go maybe maybe in 16 minutes we can go build that maybe now the the thing that I was calling out that is like why you need to make a design decision here is like you might have steps that you cannot go back
to and you have to skip over them so maybe a given step could indicate hey look like I'm transient or or something we need a good name for it like once you pass me like you're not going back to me you need to like skip over me to go back so maybe that's something that we could do let's see we'll see 15 minutes now because Nick's blabbing away okay how do we go do this well not the main window I want the wizard control okay so next requested we didn't do anything for back requested and that's okay when we say go to next step I think what we want to do is have a stack this is where I should preface like I have no idea what I'm about to do here so buckle up right that's going to help me in case go to
freeze up so this is Step history and we will initialize that stack up here and that means if we ever say go to step and what do we got so if if the current one is not null co-pilot what do we do oh I didn't want the view model oops wizard step view we just do that there we go very nice okay so I want the whole step there okay and then when someone presses back only if we can we'll go and actually what we should do is have another one of these we should always we're probably in an error state if the back button is enabled but there aren't any steps and this is kind of weird because if we're going back if we're going backwards we don't want to track the previous step so let's see we need to how do I want
to do this I need to know which direction we're going this is the the weird part so if we're going backwards and we say go to step I don't want to push the step back on on the on the history so what I might do is I'm going to call it differently um I want this I'm going to keep it on my clipboard I'm going to call this though navigate to step actually let me not do it that way I want it to break in all the spots it's being used I want this one to be a navigation and then internally I'm going to have a private one which says bu navigate forward or let's call it will be explicit track track history so only if you're tracking history will we do this and let's see where this was being used so we want this
to actually say navigate to step my my logic here or my naming is I feel like if we're saying navigating to a step I I'm thinking about forward progression so that means that navigating should always be and this is maybe my naming is not great and you disagree um I'm that's fine I'm just trying to explain to you like my thought process uh we could do we could do like a try navigate back or something like that but whatever uh go to step so this is where it's different if we're going back I would say go to and I'll rename this in just a second but rack history what what did I call it oh there was an extra X there so we won't track history if we're going back I think that's not all the use cases though that's why so we want to
be able to navigate to step here now I'm going to go rename this because I know all the use cases for it so something we could do that might be interesting is if you wanted from the outside someone using this presenter you wanted to say I'm going to control you and I want to go back um we might and even for this one's kind of weird in the first place like the fact that we can basically just insert a step from the outside is kind of interesting um this might be something you want to initialize the whole wizard with from the outside just as a heads up but I think that's going to let us go back I think it should let us so here's where it's weird like can we go back like who gets to decide that well it's the individual steps so
um if we're on the first step can we go back anyone false good okay we can't go back if we're on the first step um and if we're on the last step can we go back yes so something to think about here though is like these steps just have I did this they have knowledge this one knows that it's the first step you might want to be able to pass that kind of information into this the fact that I literally called it our first step like we know by definition of this thing that it is the first step you can't go back if you're on the first one but if you just had generic steps like you know user information input and like uh Ula agreement step like those steps on their own probably don't know if they're the first step or not so you
may want to consider if you have to go past that kind of information in so we got those things going on um we didn't make Behavior to to say like I'm going to ignore if I can go onto the history but we can maybe skip that so any step we'll be able to go back to basically so if I press next the back button here oh look at that and it preserves the state why does it do it because we didn't go remake A View model it's the exact same one that existed if I press next I press back it still works if I press next rate to the end we cannot go back it doesn't let us we could also change that behavior right so if you wanted to I'm not going to not going to do it but when we get to an
empty step I was saying hey look if you just navigated to an empty step we maybe saying that this could be an exit condition right so whatever that needs to be if that's going to close the app or something else right you might want to trigger hey look the wizard is done there's no going back it's absolutely done or you may want to design this that when you hit an empty one you just turn off the control and you're like oh I want you to be able to go back so we would change this part here to not just be false by default it would be you can go back if there's steps in the history so that's one thing you can consider from a design perspective in my opinion I would probably say hey look if you reached a null one we're probably at
the end um and then the other thing if we wanted to make it such that steps could be skipped as being part of the history we could check that here okay so how that would look is if you um put another property on The View model and you said like skip history or ignores history or you give it some other name that's better when you do that we would check it here and say oh look this step says that it should not be part of the history like just ignore it don't put it onto the stack but I think that's it folks I think that's uh it's about two hours into making a little wizard that we can step through we can go create our own steps they have information about whether they can go forward or back we are using binding um this seems
a little weird here where we have a view that we're exposing the view model on it but it's in my opinion the exact same as data context being exposed on every view um it's just more strongly typed so that's not so bad what else what else we have going on um presenters know about views right so you'll see all of the apis and stuff they're working with views but we're never touching things on the views except the view models so to prove it the wizard step view literally does not have any other properties this helps us because we can take the view and when we're doing UI things specifically in WPS like nesting controls or other things like that assigning to a Content property we can just take this thing and we know that this is going to be a control and by definition in
here it's not but based on how we have things set up it currently is so this is our literally our WPF control and then we're only operating on The View models of those things so I do like that this pattern seems a little weird but I do like the fact that everything we need to touch and interact with is on The View model itself we only pass these around so that we can put them into the user interface and folks I think that's it though so I hope that was helpful sorry about my camera situation I'm going to probably spend some time today figuring that out but yeah thanks I don't know when the next scheduled stream is I don't know if I'm going to do another one this week because especially if my camera's messed up I really got to get recording my Dome
train courses um I got to sort that out before I dedicate too much more time to streaming so we will see but thanks for joining uh at a minimum I will be back on Monday 9900 p.m. PST my normal time that's where I do my my more General software engineering AMA Style live stream so thanks for tuning in and if I don't see you later this week I will hopefully see you Monday okay
Frequently Asked Questions
What is the purpose of the wizard control being built in the video?
The purpose of the wizard control is to create a user interface that allows users to navigate through a series of steps, similar to how installers work. Each step can determine whether the user can proceed to the next step based on certain conditions.
Why did you choose to use dependency injection in your WPF application?
I chose to use dependency injection because it helps manage dependencies more effectively and promotes better separation of concerns. It allows me to pass in view models and other components without tightly coupling them to the user interface, making the code more maintainable and testable.
What challenges did you face during the live coding session?
I faced several challenges, including technical issues with my camera setup, which caused some anxiety. Additionally, I encountered difficulties in implementing certain design patterns and ensuring that the wizard's navigation logic worked correctly, especially when managing the state of the steps.
These FAQs were generated by AI from the video transcript.