BrandGhost

Live Coding in C# - WPF Splash Screen! - Principal Software Engineering Manager at Microsoft

July 5, 2024
• 744 views
Y'all want more live coding 🤨 Join me on Friday morning at 7:00 am PST for some C# fun! I'll be building a splash screen that supports background loading, cancellation, and other fun stuff. As always, AMA style so you can ask away as I'm coding. What do you want to see live-streamed?
View Transcript
started here I'm are coming through okay before I get too far along uh not really in the center of my camera there we go okay I think things are going through Linkedin looks okay I think the chat's working so welcome chat if you want to say hey and make sure that where you're chatting from is working try it out I am watching the Tik Tok chat I'm watching LinkedIn just just in case sometimes the comments are kind of weird LinkedIn uses comments for chat why I don't know um so I've notice that sometimes they don't show up in my chat um but I do have a shared chat so we should be able to see that message come through I'm going to put the chat up on the screen too and it's got some messages from last time but there you go um we are going to be live coding today which should be fun because you'll get to see me mess up a lot that's fun for you maybe maybe not fun for me but um it's going to be more WPF today so C WPF I had a request to get some content together on a splash screen and I figured this should be good to make uh give us a goal to work towards I have a couple hours before work starts here so should have something that functions and I was thinking about like what requirements do we want to have when we're building a splash screen and just a couple of things that came to mind high level or one um being able to dismiss a splash screen if possible because just to give you an example you might set it up so that you have a 3 to 5 Second splash screen something configurable right and then a user is like great I see it like go away so being able to click to dismiss that I thought would be kind of cool and uh on top of that once we have something like that Place being able to balance how that might be working if we support and we should uh background loading the entire point in my opinion of a splash screen is to have background loading you're kind of distracting your user with hey here's something nice and we're loading in the background so I'd like to make sure that we can uh try to support background loading uh whether or not we have a progress bar or anything like that um TBD I suppose because I don't know if you've ever seen a progress bar that's accurate I think uh maybe spoiler alert they don't exist so um I do want to try and make sure that we can at least have background loading and at least some maybe some type of indication like here's a splash screen you're not Frozen um because maybe you're trying to dismiss the splash screen but we're still loading data we don't want to just like get rid of the splash screen the loading hasn't finished and then the user is like why is this application Frozen so I think that's going to be the goal um um I've been kind of just messing around in this uh this solution I have for like a WPF playground is what I called it so I'll switch over to that in just a second uh the the application especially window file copies yeah yeah we've uh we've probably all seen that where you're like hey it's almost done and then it's like you know three years left so it's a pain in the butt but um I'll switch over to visual studio in just a second uh I just want to remind people that it is a live stream and I am watching chat so please jump into the chat ask questions whether it's about what you see on the screen um like that's great if you have questions about other stuff like this is my time with you so unless you're watching the recorded version in which case spoiler alert um I can't answer your questions live but yeah happy to answer other programming questions career questions anything like that so let's jump into it and see me stumble through some WPF I'm going to get my screens switched over here and hopefully you see my window and I'm going to bring my face back so you can maybe see me talking with my hands a little bit because I tend to do that okay so and I should have checked this beforehand because I think last time we were getting stuck on if you're watching my last stream this window wasn't loading for some reason um but I think we can do away with this plugin for now so I'm going to go uh back and take that out of here so to give you some context the way that this application was set up was very much a plug-in based WPF app um and to add some color there WPF uh part of the reason why I started talking about some WPF stuff um it's just been that in my history working with WPF I find that I fight a lot with some of the patterns and things that they they recommend that you're leveraging so uh I have things that I've done over time where it's made it easier for me to work with WPF and not have to um kind of avoid like avoid dependency injection a lot of WPF stuff doesn't seem to work well with dependency injection so how can we make that happen right um the last video that I was doing or last stream I guess we were talking about making this is something that I really enjoy actually making a facade and the facade was allowing us to put building blocks of the user interface together without having to care so if I scroll down to this code um we had this what's called like a Stitcher Factory here and we were able to combine user interface controls and in this case we were saying that we want to treat them like a grid when we go to do it and we could basically glue these pieces together and in this case if you look uh I had parent set to be a stack panel instead of a grid and we could still make it do grid based uh combinations of those controls so that was a fun video but the other part that we had right at the bottom that I commented out was that we had this set up to be plug-in based so I'm going to go ahead and just temporarily delete all of this stuff here just so you can see it all on screen at the same time but essentially what I'm doing is I'm loading all of the types if I highlight all this loading all of the types from my running directory and then that way we can start resolving them uh like you see down here to in this case I'm loading the main window from a plugin that main window doesn't even exist in the core application so um just a heads up for how this is set up but I don't think for this demonstration that we need to focus so much on plugins which will be a struggle for me but uh I'm going to go ahead and I'm just going to drop that other code that's on my clipboard into a method so I don't lose it um I don't know if we're going to use it at all in this oops need a void there so I just wanted to have that saved I'm I yes I should be using git and checking this in somewhere I haven't pushed it up yet but um okay so to start things off we probably need to go put a main window back in here so we have something to show but we're also going to need a splash screen so my thought process is that I I know I'm going to want two more controls at least one is the main window so that we can show that once the application is finished loading and then the other one is of course the splash screen itself and we're going to need both of those but the other thing that I want to try getting into in this live stream is um in WPF there's a pattern called mvvm so model view view model and I think in other UI Frameworks there's a lot of other patterns that you use like MVC model view controllers a really common one and again mvvm is like a really um popular way that you approach WPF but I found like it still leaves some things to be desired for me like I kind of miss having something that's like a controller or a presenter depending on you know terminology and stuff you want to use and I kind of came up with a over time like over my years of using WPF almost like a hybrid of MVC and mvvm and it essentially allows me to go have a controller to go change the state of the user interface and all of that and it it creates a separation from the legitimate WPF controls to just having like a view interface and the reason I'm explaining that is because if you did watch the last live stream where I talked about uh this code that I have on screen where we could combine things like this this all stemmed from the fact that I had WPF apps that needed to grow from windform applications so we had a mix of controls and I didn't just want to have all of my logic trying to you know flip over from specifically WPF to Wind forms and back and forth it was just like treat the logic as the logic right I don't want to have custom stuff uh for business logic that's going to change from Wind forms to WPF so I needed that layer of abstraction but as a result that's how I've been building stuff got some chat messages not sure if this is live so yes it is live hello moin from YouTube I'm currently learning CP and.net are there Project based tutorials from start to finish on your channel which I can work more on and then include them on my resume um sort of not entirely depends how much of a project you're looking to do um a lot of my tutorials are building blocks on things is how I would kind of phrase them so I do have if you go to um let me just put my website here so if you go to my website if you search for articles there I do have and actually on my YouTube channel there's a couple of videos and a couple of articles that give you recommendations for how to come up with ideas for projects and I would recommend doing that um there's also uh I always like to give John Cricut a shout out uh John Cricut has a newsletter called coding challenges so so I'll put that in the chat too I believe it's this if someone wants to check these links as I'm sending them that would be awesome but uh John Cricket has coding challenges which is a newsletter uh it's huge very popular and it's language agnostic but he gives you basically a coding challenge like is being asked for here and you can go off and build it so um I'm hoping John and I have briefly talked about it but I might be able to do a collab um article for him and kind put out a coding challenge for you guys to work on but if you look across my channel I think you'll find like I said building blocks um I've done a couple things like if you wanted to make a what's like an asky art generator like there's some basic stuff like that but between articles and some videos you should be able to ideate your own projects and just to Briefly summarize what that looks like from my perspective is that um I think a lot of people get stuck on hey I want to go build something and they think about how to make money with it and I just think it's the wrong approach if you're in the learning phase you end up focusing on tons of uh distracting things if your goal is truly to go launch a product or something like that then I mean there's a lot of other stuff that goes into that other than just code but if your goal is truly just to learn and I I feel like a lot of people watching my content that is that is their goal you're probably not watching my content because you're like hey hey I'm trying to launch my my you know million dooll SAS business in a week like I don't think that's my audience but I think my audience is like Hey how do I get better at being a software engineer and a lot of that in my opinion on at least on the tech side is just building stuff so instead of looking at how do I make a business out of my application how do I go pick the right thing to build that's going to make me money I just say pick something that's going to let you build stuff pick technologies that you're unfamiliar with and you want to get better with right and you can start with a really complicated thing you could say like you know I could say go build Instagram and you would say well Nick that's going to be impossible Instagram is ridiculously big it's complicated and I go great okay well what part of Instagram could we look at building and we just keep scoping down the problem further and further and further you might end up um you know building something that's so simple as a part of Instagram and it's literally just how do I interact with a database right I want to be able to make a schema that looks like it can store post information cool that could be a totally totally fine like first little application to go build right you're picking a database technology you're learning how to go insert and read information out of it awesome you know get that finished now you actually have a building block to go like add on to the rest of building out Instagram or something but you use these projects as stepping stones for Learning and once you feel like you're kind of exhausting um your either your interest or your ability to kind of feel like you're learning new stuff about that Tech I would say great like you can go move on to something else because the goal is learning not to go finish something and sell it to millions of users so that's the framing that I like to give people and I hope that it like gives you some flexibility about the stuff that you can go focus on awesome code steps it's great to hear uh uh I glad that that's been inspiring um I've I've always or I shouldn't say I've always but I have shared before that when I started my channel off um there's two big YouTubers that I really like so you probably know them Nick chapsas and uh Milan javanovich and I've told them and I I never know if this comes across the right way sometimes I feel like it might sound like it's uh negative but it's I hope that it's flattering for them but I was watching their channels and I have for years and I went like uh at the end of 2022 I said I think I can do this and it's not like Nick chapsas and Milan aren't great at what they do but I just remember thinking like they've been so consistent and I think that if I just am consistent with creating content that I can do what they're doing now again they're amazing at what they do and I think it will take me time to be amazing like them but I said they're doing it they're being consistent I think one of my superpowers is that I can be consistent so 18 months into it I'm I'm hoping that I'm building that super power up but um yeah it's uh it's great to hear if uh if my my work has inspired you to go make your own channel that's super cool uh would recommend looking at code cus too they're there for you to keep practicing against and continuing awesome yeah that's great thanks for sharing that Sean um thanks coding child I appreciate that um moin cool yeah like let me know um you can always reach out to me on on social media like so after this stream and stuff if you want to send me a message on pick a platform um LinkedIn works well uh I get I get a bunch of connection requests so connecting with me isn't really the best thing but if you want to send me a message my profile's open so you can send me a message and say hey I was asking this on on the stream let me know if there's more data um and we got John in the chat on LinkedIn hey John John has uh where's the link to this uh I want to get a link to John's stuff one sec John where is your stuff it's uh like it's not levels FYI um give me a moment why can't I why can't I think about it John it's this is what happens when you stream I'm just searching John's profile so I can get it latterly that's it thank you latterly so this is just because John dropped in uh people so John puts out a lot of really awesome content for people that are trying to get into uh industry uh I really like what he's doing there we go he yeah John put in the chat as well thanks uh clearly I can't multitask I can't think talk and type so um yeah definitely check out John's stuff highly recommend uh I always love plugging like after I did my interview with John John's got a PhD in economics and it's it feels like it's very obvious when you talk to him because he has a lot of knowledge and like data which is cool because even for myself when I'm talking about things a lot of it's like I've been doing this for a long time here's my opinion on it and John goes well you know I've been doing this for a long time too and here's literally data that I can site and point you to and I go okay like yep awesome it's super cool to have that uh when people are backing stuff up so thanks chat thanks for being interactive I'm going to keep going with the code here uh but by all means please ask away or shout at me if you see typos and stuff or something's not making sense so the point where I left off was that we're going to have these two controls at least two windows a flash screen and a main window um we might start to see some of this other code come back where we're able to glue these pieces together but the other thing that I was talking about was that I like building this hybrid of mvvm and MVC and I haven't given in a a fun name a little fancy acronym but it's it's mostly it's mostly like MVC but when we have the bindings and stuff for mvvm it kind of Blends them together so with all that said what I like to be able to do is think about the logical flow of things and less about the controls themselves I've already told you that we're going to have two windows we can come back to how they're actually presented and what we have to do in the user interface to me that's less important to go to focus on to start with because we know we can go build any two windows right and just to prove it like I'm going to go add two windows to start so we'll do main window come on visual studio so we'll get a main window dropped in cool and what what's a good way to do this maybe I will do it has a title main window but we'll do on the grid a fun thing I like to do that hurts everyone's eyes is we're going to just have some really bright colors so we know exactly what we're seeing as it's happening so we have a main window set up it is cyan in the back ground and last time I did red green and I realized it's probably the worst uh not very thoughtful of me so I will not pick red and green this time but we will do another window this will be splash splash window and again we'll give the Grid on it a fun background color what's a good one uh magenta two colors that should hopefully hurt your eyes and make sure that you know what we're looking at so our Splash is is going to be magenta when we see magenta that's the splash so now we have two controls but like I said you know you can go spend all the time in the world you want making these controls look nice and uh again because there's about an hour and 40 minutes left here instead of me going oh how am I going to design how pretty this Splash ring is going to work spoiler alert it's not going to look pretty but you can go spend like I said all the time in the world that you want to go make those things pretty do whatever you want maybe you just want a picture there doesn't matter but I'm going to start trying to think about the logic for how we go present this stuff so um to start something that we might want to do and actually yeah let's do this so I'm going to make a new class let me pull this up on the main part of this the window a little bit so I don't know if I want to call these things controllers or presenters but I might call it a presenter just to I don't want to I don't want to attach too much terminology to the classes I'm building so so people watch and go well in MVC that's not exactly what a controller does like I I don't want to attach too much bias there so I'm just going to call it a presenter so um we will have a a splash presenter and the goal of the splash presenter and let me go even back up here is I want to go thank you co-pilot so what we're going to do is show probably do this so we will have a method to go show the splash screen and then after what we can do is we can do this a couple ways so we can go get the main window and then ask the main window to be shown um or we can continue the pattern this might be Overkill in this particular case to have a main window presenter I don't really know yet so we might be able to do that and I could do the similar thing let's see if co-pilot picks up on it yes it does um we also generally like to have cancellation tokens on things just I would say even if you're like ah you can't cancel this um I say think about it default I don't have one yet but I like building the apis such that they're there and another thing to call out because we're here is you if you're familiar with asyn a weight patterns and CP if you come from um working in asp.net core you generally don't think about this because people will say oh it doesn't matter because you don't have auler the same way that you do in WPF and Wind forms but and these methods don't exist so the intella a sense isn't working but there's this thing called configure a weight and if we put F oops don't do that if we put false into here what happens is that we are able to have an awaitable method and when this comes back we're saying with configure weight false it doesn't have to come back on the same thread so I'm going to start dropping this kind of stuff into the code but it's going to mean that we have some things to think about and to explain what I mean by that when we're dealing with user interfaces and different threads one of the challenges is that you're not able to for like 99% of use cases you can't really be interacting with user interface controls off of the main thread a lot of WPF for sure Wind forms for sure probably lots of other user interface Frameworks they have a main thread to use for layout painting it's really just like a render thread and accessing controls directly from other threads generally leads to like some cross threading issues where the framework itself will say like hey you can't do that like just not supported they need to check if they're on the main thread so I want to sprinkle this stuff in because I'm hoping that we can start to see some patterns show up with that where we go Hey look it's broken and then we can think through like well why is it broken right we're trying to show the splash screen um we're going to do some background loading but if we come back from showing the splash screen and then we're on a different thread and we try to show the main window what should happen there uh another thing I want to call out and this is maybe a little bit pedantic but a lot of times you'll see people saying when you're doing um like using your dependency injection container so that's what the service provider is it's the container that has all of our dependencies in it and we can ask for them a lot of the time you will hear people saying like to I'm going to use air quotes here to do it properly you resolve the one main entry point and the fact that I have to do two like this might be an indicator like you're doing the wrong thing so in my opinion like whatever this isn't a big deal at all we want a splash screen that we want to show a main window no big deal but what we could do is make it such that the call to show splash screen when this completes internally it already has a reference to the main window presenter and can call it directly so uh what I'm trying to say is this code that I have highlighted if I cut it out if we imagine that it existed inside of here at the end of showing the splash screen that's one way you can kind of chain these things together but I don't want to do that quite yet so now we have these two things that don't have methods uh can I use a little bit of the refactoring menus to go do that for us looks like yes um this is a Constructor so we don't want to do a syn8 inside of a Constructor that's a big uh that's a big no no so we can go refactor this a little bit more I am going to take this out um on this code here I'm going to pull it into oh there's no quick refactor for that I'm going to make it a instance variable I could spell service provider so if you haven't tried it before try doing a a live demo at work and uh like coding things along the way you'll find very quickly that and maybe maybe you're just naturally an expert at it but um typing talking in front of an audience is like not it's not easy um that cancellation token doesn't exist there anymore we do have a method so we have an event handler both of these kind of suck because they're not async but uh maybe we don't even want to do async on these because they're UI based so you know what let's go do this what I'm going to do is get rid of the Ayn part so I might have been jumping the gun we don't necessarily have to do that uh oh that's weird I thought I generated two methods I guess I didn't that's okay so we're going to have both these presenters uh show splash so and we don't want to Splash T so we're going to do that and then we're going to do the same thing with the main window so this method maybe not we have to think about how this is going to work from an asynchronous perspective because when the splash screen's showing we don't want the application to be locked up that's the big thing so we might have to think about how we're going to handle that in here we could go launch a task and wait for it so let's start with the splash screen we'll come back to the main window but you know a super simple way to get started here is private we need a we need a reference to the splash screen because on our presenter we're going to be using that to show it right so on the outside we're just calling this presenter that has the logic it has the API we want to use to go showing the splash screen but inside here we are going to know how we do that um and it's kind of funny like so they they've already put like I didn't change the signature again it's still async and co-pilot was like Hey look here's how you go make a splash screen right we're going to put it up do a delay of five seconds and then close it but that means like this is generally what you should not be doing I have videos and articles on this but um we might end up going down this path on Startup is was synchronous and I put async in front of it now we can do a weight here but this combination in C async void is like one of the most dangerous things you can be doing and it's because when you have an exception that crosses the boundary so anything inside of here that throws an exception and goes beyond this async void boundary is just absolute chaos um you're can have a ton of problems in your application and not understand where they're happening because there's nothing there's no like part of the your call stack that's able to handle that exception so I think because this oops my control key is locked that's funny okay there we go um because this code is super simple we should be totally safe right now so if we go call show splash it's async so we await it this should technically go put up a splash screen for 5 seconds it's not what we want but uh let's go see it work I'm going to try to move the window over as fast as I can okay so there's our Splash Window right you can see me move it so it's not locked up and then it's gone so that's kind of cool right we have a Splash Window that's able to show we can uh use this async pattern to not have a locked up user interface and we can go hide it so not a bad start um something that we want to think about though is I talked about a couple things so uh some conditions so one can we close it early to Pilot that's not it's not what I want can we close the splash screen late um sure sure you could um can we do background loading so what I want to think about is this idea that if we're showing the splash screen window I want to not just wait for 5 seconds I want to make sure that we can go run some background work and basically if the background work finishes very fast then no big deal right but if we put the splash screen up and we're saying we want it to be there for at least and this is the the keyword here at least 5 seconds or at least 3 seconds whatever it is if the background loading is still happening we need to wait for that to finish so it's kind of like the maximum between the two and I think that's kind of an important thing for us to think about here so um how I might want to go think about doing this is we could have something that's like task do and actually I think the way that we might want to do that is this way and we pass in a cancellation token here I will put this onto a new line um do heavy work a sync there we go so this is another task and we could also maybe have a parameter that's like time span um minimum so what I'm thinking through here is I have I want to start parameterizing some of this because I think what we're going to have happen is somewhere in here this is just waiting for a 5-second period right so here we go now it's variable so that's a nice little enhancement and by the way I'm just coding random stuff I'm not like I don't have like a true spec I'm working towards I'm just thinking about some functionality that I might want in a splash screen so if it seems like it's a little randomized it's because it is so we have this task which is going to control the minimum but I also said we have this guy going here we need to wait for essentially we need to wait for at least this one to finish so um the way that I would think about doing that is let's see if we have a task we'll call it minimum weight task so we have this task but we also have this and I didn't have a cancellation token so let me go put this back we are going to go with the async pattern here that means we want a cancellation token here we'll propagate that whoa keyboard we'll propagate that through did I spell it yeah I don't know what happened so I switched out a USB hub so I know what it is I just don't know why it happens I switched out a USB hub and you can see that I typed cancellation token and it's like the c key on my keyboard just got held down randomly it's the only thing that's changed recently so I don't know what it's doing so now we have these two tasks right we could wait for we have a couple options right we can do task when all we could do task when any we could await just do heavy work we could await just the minimum await task minimum weight task sorry so I'm just showing you a bunch of options so we can talk through them for what we were interested in hello Hussein good to see you I was expecting if you were going to join it would be from LinkedIn so awesome to see you on YouTube so the the thing we have to think through here is like okay so if we're only waiting for the minimum weight task I don't think that that's right so I want to kind of document these right this won't work because we could still be doing heavy work okay so I don't think that's going to work if we only wait for this one um I don't think that this works either so this won't work because it might be faster than the minimum time and I think then by definition this one doesn't work either does co-pilot figure it out this won't work because we could still be doing heavy work yeah and we could also be doing it could be faster right it's like this line is either of these and both are problematic based on our definition yeah it seems like it should be a max weight time right so it's when all now the reason this is a little bit tricky still and I just want to highlight this is this line here on line 110 this comment so we'll come back to that but I do think what what we want is this and that means if we think through what we got going on here if when so when all means we have to wait for both of these right so if there's a minimum weight if this one let's do this okay so if we do this and these are the times that each task takes it means we're going to have to wait kind of like what uh Brian's saying in the chat there we need to wait the full 10 seconds and that's what we want because if we only waited the 5 Seconds we'd still be doing work we can't end yet right and if we flip these around it's just the same argument the other direction it's just I want to vocalize it right so if the minimum weight we said we want this splash screen to always be up for 10 seconds if we're still so the heavy work finishes fast we still want to wait the minimum 10 seconds so it does need to be when all but like I said the weird part that we're going to want to think through is this because if heavy work is done so let's go put this back if heavy work finishes in 5 Seconds we should be allowed to close the window and interrupt this minimum weight right so and maybe I picked Min the name minimum weight is a as a bad name but my thought process was like a minimum uninterrupted weight so if a user is not clicking to close it right they can't click to close it if we're still doing work but if we set the splash screen to be 10 seconds and the work finishes in 1 second and they're like I don't want to wait here anymore they should be able to close it so I want to work towards that but we can kind of address this uh in a little bit I think um and we might be able to do that with some instance variables and stuff but if we go try this let's go see if there's a way that we can make this oh I need a cancellation I need a bunch of stuff now okay so that's what I get for adding parameters we want and I'm going to name name them on here so we can see thank you co-pilot um we'll see what's up I wonder I'm very curious to see if there's a way that we can make this a little bit more obvious what's happening so what I might because I want to show that the the heavy work is happening right so what I might do is uh four yeah something like that thank you co-pilot but I think I might want to do yeah okay let's do this and then what I'm going to do is every iteration so this is still going to wait a total of 5 Seconds because 10 times 500 is 5,000 milliseconds but I want to do a debug. right line let's do waiting in do heavy okay so we're going to do that and we're going to print out to our W our debug window that this thing's running so hopefully what I want to be able to show you is that we put this splash screen up I want to be able to move the window around to show you it's not locked up and that this code is just running in the background so let's go ahead and do that okay waiting and do heavy work you can see I'm moving this Splash around does it close it closes okay so that's good um now what did we do for parameters so it waited a full 10 seconds I'm going to run this again because I wasn't paying attention to that but you can see that it's saying do heavy work and I'm moving this around do heavy work stop it's still going to wait that full 5 Seconds to give us a 10-second splash screen yeah and then so the the YouTube comment here sorry I don't know if I can pronounce your name properly and I don't want to I don't want it to sound insulting if I try s Janos um Janos uh maybe you should calculate when the minimum Splash time ends and check it after the heavy work yeah so I think if we want to get to the point where we can click to close um instead of doing this in one line so thank you for calling that out I think this is the direction we will want to go instead of doing this in one line right if we break this apart uh oops that's not what I want a wait really co-pilot um so await minimum weight task like if you do this you were awaiting these sequentially but the interesting thing is like they've both started okay so we have these tasks we're awaiting them sequentially so we might want to do something like this where we can at least or maybe the other way around sorry literally I just inverted what was said in the chat so if we always we know we need to wait for the heavy work to finish no matter what we can't close the splash screen if we're still loading but the minimum weight task that's a little bit special because that's the minimum we want to wait if someone's not going to interrupt us but they can interrupt us if this part's done so we might be able to do something kind of cool there um now how we want to do that that's a different story and I have I'm kind of thinking about this on the Fly By the way because I haven't had to make a splash screen like this in probably now like six years so it's been a little while so I do think this is what we want to do so we'll put a too we can do something like that um okay so far I'm not upset with this let's go run this again to make sure it does what we expect when we wait these back to back so I can move this around heavy work is done this is still up it should be just 5 seconds after and it is right so this gave us this it's just that now we have the option to potentially do something different here okay so I think that's a good start um what's a way that we might want to think about this I think cuz what I I want to show you as well and I don't know if I'm doing a good job demonstrating it this is a presenter this is all logic and I don't want to be directly and we're going to come back to this in a second I don't want to be directly working with WPF controls here I want to work with abstractions of them and again for your use case um this might be totally fine you might not want to do the level of abstraction that I'm showing here and that will be totally up to you totally cool um I want to call out why I'm doing it so that you can decide if you want to make such a decision for a typical WPF app it might just be absolutely Overkill um if we go put an interface for Splash Window as an example you might say well Nick I know that I'm only ever working with WPF so it's not a matter of swapping the technology out so first of all I just don't care for that and that's totally cool and then the next part might be okay well if the technology is the same do you ever want to swap the implementation of your Splash Window and you might say well no why would I ever want to do that and that's totally valid right I'm not saying that it's a thing that you need to go do that I have these patterns from overtime that I like to use because when I am comfortable doing them they don't seem like any extra overhead they are in code but they afford me some other things because when I ask you the question do you ever want to swap the implementation of your Splash Window when you tell me no I go that's a totally fair reason but then I say well don't you ever want to test this thing and for me I want to be able to test it without putting a window up on screen um we we'd have to go change our task delays and stuff to be testable so we're not going to go wait like 5 seconds or whatever but one of the reasons that I like having interfaces on my controls instead of the controls themselves is so that I can test my logic iCal flow and it's one of the reasons that I like having presenters or controllers I found that when we start dropping and this is one of the things that you're probably all familiar with if you've been building user interface uh applications right like a lot of the time we're pushed away from putting a lot of code behind like code behind on a control should be I say should be not has to be but we try to make it such that it's very focused on what the control is doing doing from a presentation perspective right how it looks maybe the layout stuff like that but not business logic we try to pull the business logic away and you know again for me one of the reasons for pulling the business logic away is that I can have the business logic completely separate from the control and I would love to decouple it from WPF entirely like that's where I like to get to with my levels of abstraction and again you have to think about the context you're working in if you're saying Nick at work we're just building a WPF app and that would be absolute Overkill I agree with you you don't have to do what I'm going to show so I do want to I'm already losing my voice good start to a Friday but I'm going to go start putting an interface on here and it's going to be I I splash screen now kind of interesting this kind of um I know we've been talking about splash screen and I called it a Splash Window um this is actually a little bit of muscle memory for me so uh some of the naming that I use to use is the implementation of the thing we're talking about I almost always will name base on the WPF or wind form control right so it's a Splash Window because it is a window and I purposefully called this splash screen instead of I Splash Window not only because it is a splash screen but I was using the word screen to represent the abstraction of a window what I mean by that is in WPF we literally have a window in Wind forms we have a form if you're building like what I was doing was uh building stuff in unity as well so what controls do we have in unity well I don't know it might just be that you want to call the thing you're looking at it might be a scene in unity but I would just call it a screen it's my abstract to refer to all these things because the presenter doesn't care about the implementation of the technology right that's the point I'm trying to get across here so drop that on drop that on and we're going to start to see that we have some compilation errors right there's no show and close so co-pilot thank you feel like feel like I should be getting some some Kickback from co-pilot when I'm doing these videos right I guess I'm employed by Microsoft so it just it helps but now this works except our Splash Window needs to go have that interface on it as well so very simple because the splash screen has two methods show and close and window also does two so we get those for free what did I just go do well nothing really useful in terms of functionality but now this Splash presenter doesn't depend on anything that's WPF specific I think that's pretty cool it seems like it's a trivial change right but literally this thing doesn't care about WPF at all now it does mean that we have to kind of move our mindset around because and I I want to explain why I did this as early as I did what we're about to do is try to hook up some stuff onto the window itself that we can go click it to interact with it or have a close button whatever you want to do but that interaction is going to be very WPF specific so again if we can make it such that we click on any part of the window and it can intercept the click to be able to close that's WPF specific if we want to put a button onto that splash screen that says close like putting the button having the click event handler that's very WPF specific this thing just doesn't care about that so if I didn't make that change I wanted to get to a point where this thing doesn't care about it so it my opinion we can design it to be what I would call a little bit more clean I hate using that word um if I didn't make that change we get a lot of access we get access to the entire window and I feel like we might be cheating a little bit because we have so much access to it so I wanted to kind of put something in place where it's like look I want want you to consciously think about how you're interacting with this thing and that way if you want to swap your window out for a wind form or you want to do something entirely different having uh mocks or you could even because I've done weird stuff like this before you could have your presenter show console data like you could literally go make a splash screen that's a console right okay that's why I wanted to do it hopefully that context helps I know it might seem like Overkill though so at this point this is the thing that I kind of want to figure out and how we go do that so we know that we have two tasks to wait for but after this first one we can go do something more so what we could do and again I haven't fully thought this through but at this point we could say can um and I don't actually want to do this on the window directly we're going to this is going to be funny we might not even want to take in the window itself or the splash screen we could be working with its view model so that's kind of neat The View model would give us that abstraction as well so just to give me one sec because I want to kind of walk through this thought experiment if we have a Splash Window here I'm still technically directly talking to the control right thanks suan I appreciate that um if I go to have this Splash Window here if I put um like something like can click to close maybe a terrible name can close early right we could do that and then we could essentially allow the Splash Window to have something else that can close itself that might be kind of weird because what if we have other logic here so if we can do a can close early I wish I I should be drawing this out it's kind of messy to to think through but if we can close early what happens if the window itself is window yeah let me it's better English there what happens if the window is responsible for closing itself so we say Hey you can close early and then basically it's like cool and it handles literally allowing the user to close it if we had other logic here it might get kind of weird so we have to think about what we want this interaction to look like I don't think there's a right or a wrong answer here I just want us to be cognizant of it um sometimes what you'll see is if we go back to the splash Windows Amo sorry that was that the Gent is very jarring I I have regrets um but like I said you'll know when it's the splash screen right um if we know how do I want to say this okay so if we have a window like this it has these controls in the top right okay so the fact is that when this thing's up if I just go run this now oh crap sorry I left this code in here come on get out of here visual studio if I just go run this now like I closed it right I cheated is is that what we want to be able to have happen in our application like I don't I don't know you have to make a decision about that because you might say like yeah like someone should be able to just close it and you know that's going to terminate the app because they didn't wait I don't know um I can't remember the State no I can't remember what it's called um it's been too many years one sec WPF hide uh minimize button that'll tell me there's a a a property but oh no someone's talking about using yeah resize mode that's it thank you tool window oh yeah you can make but it's what's what's it called is it a type or do you change the the actual so it's not that but you can set a type right I thought but there's also this resize mode so that's not what I want let me just search WPF window Style thank you I've said this before um that what's really cool about live streams and I don't know if people notice this but when people are interactive in the live streams it's literally like pair programming and if you don't see the value of that just from being in this chat like that Brian was able to see what I was doing I have a microphone Brian doesn't have a mic right and he's just able to to know what I'm doing and jump in and say like no here's the thing you have to do um so I don't know if that was um exactly it but there tool window is it just not updating it let's see what it looks like okay so that got rid of the minimize maximize but there's still an X so what's the setting for that um I know there is a people are still saying P invokes but I don't think man I thought that there was a way to do this there's a lot of people saying P invokes but I thought you could do like a borderless window maybe that's a Wind forms thing there's no wow amazing resize mode if you're in the chat and you know I'm trying to get rid of this X and I thought that there was an easy way to do it I thought between resize mode and there's Windows state but that's not it at all I thought between these three things that it covers that this one says set window style To None that's okay that there it is so Brian thank you I think all of your input led to exactly what I wanted so now we have this splash screen and it's popping up in a weird spot there's another thing that we should talk about on a splash screen though so Windows style none is nice because you can't just go close it right people are hijacking the window although there is this weird behavior and it's not a big deal like you can you can't press escape on it but you can press alt f4 but if you wanted to press alt f4 anyway you're trying to exit the app not a big deal um there is this startup location um because this is the splash screen center screen to me makes sense now it's not going to look good for you on the stream cuz you see how it's in the bottom corner behind my head that's the center of my monitor I'm using one quarter of my screen to to stream to you guys but that's like that's the kind of thing that I would want on a on a splash screen but now we don't have um the border to close it earlier so this is part of what I wanted to address okay and we just have to kind of think through what we want to do here so um I want to make sure that we can enable the control you bind the window style yeah so what we could do is basically this change here right we switch it from nun to Tool window like that's what the binding would be able to do so um and Brian said binding which is good this is kind of getting at what I wanted to make sure we would avoid right I don't want to be in this position where I'm talking to the control directly and then I say like window style and then I go like whatever the system what okay so what name space is this in so this is in whatever I'll see in just a second Windows style is in system Windows Windows style in my presenter I would like to have like I said I want this to be as agnostic as possible so this is the functionality we want but I'm trying to make it agnostic and sorry Tik Tok is trying to end my oh it did end my live stream wow we don't Tik tok's kind of crappy for streaming um I'm doing that again just starting off the stream it's really weird it's like there's people joining people watching on Tik Tok and it's like there's inactivity so I'm assuming people need to be chat on Tik Tok or else they'll end my stream which is dumb so anyway this is the behavior we want to have and we could do more we could go put a a button we could go make it so that you click on the Splash Window and it will be able to close and stuff so like we could do that the other thing is again if we go make this a twool window it can close but do we want that or do we want this presenter to be able to to handle the closing for us so that's something to think about I don't know especially I haven't given this enough thought but in the next hour I'm not sure that I'm going to arrive at a solution that I'm totally happy with um I generally I like my presenters having full control over what's going on so if the window itself is able to close itself and that might disrupt this kind of state that follows I might not like that but it might be totally fine for what we're doing so we can go approach it that way especially because right now there is no other logic that happens after here so it might not be a big deal um the thing that I'm not liking that I wanted to come back to is this presenter the way that I used to do this kind of stuff is like I'm kind of cheating a little bit I'm calling methods on the on the control itself and I don't think I should be doing that um I liked previously passing in these things so that I could structure the user interface so if I needed to go just to give you an example if I had a window or a control I would use a presenter and have a reference to one of my controls this way only so that I could go add children or remove children or whatever I needed to on the control itself um but I don't necessarily like controlling the state this way um like obviously this is not what I would recommend cuz this is directly oops directly touching the control again I'm talking about abstractions here like this we could go switch this whole thing back right like and be done right like this this basically does it hopefully we'll see right there's an X you can close it done so you might be watching this going well why are you over complicating it and I mean the answer is I mean that's how you go do it that's the easiest way it's already done um what is still kind of weird though is like let's do this now um I'm going to put a debug right line here and another debug line here and we will do up here okay so I'm going to run this again we're going to have these these right lines out to the console to watch for if I close it oh crap it ended the application ah man let let me I got to come up with a better example here I'm going to show the main window after we we do this thing ah let me cheat a little bit here um sorry uh what is my name space WPF playground sample application I wasn't expecting that to happen because uh there's no other window like it's just done so no main window dot really okay so I still don't think this is going to work if we close that if we close this right away there is no main window so this is a this is an interesting situation if you close the splash screen and there is no other window it's just going to end so we have to be a little bit more intelligent about how we do that okay um that might mean that we don't want this maybe or we do again I'm I'm moving a I'm moving back from the interface just so we can quickly iterate on this you might do Splash window. closing okay and then we could do we could basically break out of here you could do um oh what am I talking about let's do another cancellation token okay so um and I want to do a linked token how does that work so just to explain what I'm doing I'm going to basically let's call this Min I'm just trying to make the name a little bit shorter because I don't want it to run off my screen while I'm streaming I usually will give things very verbose names but just trying to make it a little bit easier on the Stream So what oh sorry that's absolutely not what I want a wait there we go dot token thanks for bearing with me on that that was a bit of a brain fart so what I want to do is say hey look if someone's trying to close this let's go cancel the weight task and I actually don't even know we might not even be able to hijack this in time um and this is maybe another reason why we want to do the main window presenter so sorry I'm jumping around here I'm just I I think I might have a a solution for this um okay we had where was this code on Startup I I was about to put this other code that would show the main window after but we're not going to do that we're going to pass in the main window presenter and the point is that once this thing's closed we'll go show the main window okay so if I go here now we need to go set this thing up thanks co-pilot just press Tab and you have a program so let's walk through what this is doing now though we're saying that like we're kind of hijacking when someone's trying to close the Splash Window we're going to make sure that we're showing the main window and I don't know if this is sufficient right now I'm just focused on if someone PR presses that X are we able to say hey wait don't terminate the whole application we need to make sure that we can go show this main window but the other thing that I'm doing here is trying to cancel that um that delay I don't know if that can I hate cancellation tokens for this reason I don't know if that's going to throw an exception we'll find out so press the X okay so doesn't like that that's fine um I wish there was an if you are familiar with a nicer way to do this um let me know but I like this feels like the most terrible thing ever uh but it seems to do the trick or operation canel exception works too so let's try this again I just want to see if the application stays up and it does look at that so that's cool that happens if we close with the X if we just leave it so I'm not going to click on the X when it comes up we're going to wait the full 10 seconds together and we'll see still works right so this is interesting this might be Behavior we want to stick with I still kind of think that this is um a little gross like we still have this Splash uh window close and it doesn't have to get called if we've gone through this path my control key keeps getting stuck so what we might be able to do is continue with I'm just thinking about this for the first time sorry so we call it like this and I'm just thinking that if we wait for that minimum weight and it's not cancelled we can go move this code there and what's the task continuation options only if run to completion okay let's try these two scenarios Again by the way if I wasn't using the control directly and we using interfaces I could be writing tests on this calling thread ah there we go there is our first I knew it was going to happen on stream I'm glad I talked about it at the beginning this is our first cross thread operation this is happening on a background thread so how do we get a dispatcher again how does this work H WPF dispatch main thread this has been a long time got to love the dispatcher yes oh it is oh on the application or any UI elements dispatcher H okay okay this is cheating and it's cheating because and we'll come up with a a solution for this hopefully before the um the stream's over this looks real nasty but what's let me see if I can does that help I don't know it's still pretty gross we are we have this minimum weight and when the minimum weight finishes only when it's actually ran successfully we're going to close the Splash Window because someone else didn't close it for us and we need to go run on the main thread the reason I was saying that this is kind of gross is like I said if I want to get away from using the WPF stuff specifically like I don't want to go ask for someone's dispatcher like that to me is just weird it means that I have to understand that it is WPF and it has a dispatcher so I would want to to change this around but I'm I'm realizing that on this stream I might not be able to get to how I want to use um those abstractions properly so let's kind of focus on getting this functional before we focus on getting too abstract so I'm going to let this thing run again hopefully it closes on the main thread and it's all good to go couple more seconds here boom Works we're happy with that very nice now I'm going to run it again but this time I'm going to press that X after 5 Seconds ready fire away also works I'm just kind of waiting to see except you can see exception Throne task canceled exception so we canceled that thread right application current dispatcher thank [Laughter] you excellent okay and then the way that this would work is I would want to go one further if you watch a lot of my stuff you'll hear me say that I hate watching or hate watching hate using static references to things so this breaks a lot of my uh design philosophy but this type is a dispatcher is there an interface on this thing no why would there be right that's okay so I like to do this so I just realized it's not a primary Constructor it was throwing me off so that's how I would like to do this not ask for it from this context but up when we go create it and this is kind of funny I don't know I doubt I doubt that's going to be exposed with screw door and the uh the service provider yeah it's not so it it doesn't know that which is fine um I know exactly how to do this with autofac I don't know how to do this with um the built-in dependency injection stuff yeah the par programming part is awesome especially for me because when I'm sitting here being like oh this is so embarrassing I don't know what I'm talking about soone just like here here's a on line like go fix everything so I do appreciate it um so this is how I would probably do this kind of thing in real life I would go I'd come back to it um it's not going to end everything for me I know that it's very doable to pass pass Us in with dependency injection uh part of if you've been following a lot of the other content I've been making I've been trying to move away from autofac it's the dependency injection framework that I love to use but I'm trying to move away from it because a lot of the stuff that I'm finding in asp.net core it's so entrenched in and it's a good thing it's so entrenched in the built independency injection framework that like I'm finding using autofac now is like I'm fighting with a lot of things that way hey rambling geek good to see you again um yeah Brian saying we have an old app where that's nearly every Constructor for our view models yeah it's not it's not great right like we don't want to be doing this kind of thing um but I just like I said with autofac I know exactly how to do this I don't know how I can uh like hijack the construction of that using this pattern yet it's got to be doable I have to spend more time doing it um you know just to give you an example I mean we can we can solve this right with one more level of abstraction so I just want to show you that this is how you could do it I think uh Splash presenter there you go this will go solve everything um but it doesn't actually it just means that if you went this direction you just move where this is right because the point is that if we wanted the splash presenter Factory they can go make one of these then we could go pass in the dispatcher through here but now this uh Splash presenter Factory has the same problem how do you inject that dispatcher in so I'm not going to go down that route it's just a a thought experiment if you wanted to move things around so let's kind of have a little look at what we got going on here I'll clean up some of the comments um by the way because we are doing some lovely pair programming together does anyone have patterns they use for this like I don't care if it was cancelled just keep going build a small app uh Windows forums 4.8 using any framework corn performance isn't great yeah I don't I'm not a fan of any framework core um just I find if things aren't working the way that I want there's too much magic in between me and the sequel and I would just rather write the sequel um I feel like Entity framework core works amazingly for two groups of people one is people that know nothing about Sequel and they just kind of started with code and they can just write stuff or the exact opposite people are like very good at SQL and they know how enity framework can just like skip a lot of that heavy lifting for them um I know SQL but I feel like I haven't spent enough time with n framework core to understand how it's going to replace some of that stuff for me but yeah even like Sean's saying uh Dapper is my normal go-to um I had heard about so I started using Dapper this year and it's funny because I was trying to use Entity framework core and I was like it's not it's not going so well for me like why am I fighting with this does it feel like I'm doing the wrong thing and then someone was like Hey try Dapper and I'm like yeah I heard it Dapper okay and then I tried it and I was like Dapper is literally how I write my uh my interactions it just saves me one complete step it plugs in perfectly to how I like to write code so um oh and rambley geek saying it wasn't and it wasn't core it was full framework why you doing that man get on get on core core is where it's at I understand there's potentially some constraints there so um anyway if people know or have a pattern for how to do this um yeah let me know cuz I hate I hate doing this kind of thing like I want this to be cancelable and just be like cool like continue on um maybe I'll search that uh C pattern for handling task cancelled is I haven't yet seen something I like stack Overflow I haven't read this yet so we're going to read it together okay so literally the thing that we're looking at right oh man that's not that's not what I want man I'm trying to see if there's like a oneliner that's like we just just don't care okay this still feels like it's a lot though oh interesting but that's not it's not really what I want hopefully this yeah they're literally just saying do the same thing I does someone have an extension method for that could we go write one super quick I just feel like I'm not the first person that thought about this right okay um maybe we'll spend a couple minutes so continue with does that actually just work thanks for suggesting that in the chat Steve I'm just curious like do I have to put that continue with okay here's I'm just going to I know I have the microphone and you don't so this is kind of unfair to be like hey like there's a delay too like hey Steve answer this for me so I'm going but do I need to have that continue with all the way up at the top like do I have to slap that on to Oops why is that so crazy do I have to go do that up here or is there a way that for any task that I can go do it like that because I think this is what I would want to do and I don't know if that works it does okay it does work let's see that's why I said I can't be the first person that's been like why does this suck come on [Music] Steve oh Steve you are a savior that is so cool thanks so much I can't believe that worked that's great I didn't know that um I wonder I wonder if there's any risks associated with that like this is going to swallow any exception I guess so and again I don't mean to put you on the spot so I'm just thinking about this because I haven't I have never seen this in terms of a solution but it looks like if anything else happened in here it would so if we threw an exception for any reason would it just be hidden because ours is literally a task delay it's like it doesn't matter task delay shouldn't be throwing any other exceptions except cancellation um I'm just curious though if there's other tasks that we're we're running some background stuff like polling and we just want to end it right and then it throws a task canel exception that polling could throw an exception for another reason we might want to know so I'm I'm thinking that this might be a little bit too heavy-handed but I just don't know um anyway that's really cool that this works I I just didn't know that existed okay um I'm trying to think what else I might want to tackle here so we have a functioning splash screen right the the part where it's actually doing work is pretty boring um if you wanted to be able to um if you wanted to be able to have some type of progress or something like that this gets a little tricky because if we look at the API we have do heavy work async call back the person who's doing the work we're not giving them a reference to anything we're just saying you go run work if they're like hey well I want to update the UI to say like here's the status or here's how far along we are they don't have that option because you're not get giving them anything to work with right so that's one thing to to think about because in here like I'm writing out to the you know to to the output window the debug console but if you were like I want to be able to do like ah yeah so sorry I'm I'm reading Steve's messages in the chat because I was very excited about this said I wrote some extensions to rethrow everything except the cancellations perfect yeah so that's kind of what I was thinking just to highlight if we go back here I think I think Steve's agreeing with me that if you do this it will end up being for other situations other than like a task delay probably too heavy-handed if your task throws an exception it will just get swallowed we only care about the task cancellation ones to say hey look someone canel this it's cancelable that's cool like let's keep going um we need to be able to rethrow other exceptions so Steve was saying that he has a an extension method for that which is I think super cool Hello Vlad on YouTube good to see you here um okay so what I was trying to say up here is if we wanted to be able to do Splash Window like um I don't know uh we're going in increments of 10 so it's like plus equals like if you wanted this kind of thing we don't have it and that's because our call back doesn't have it so we could and I'm not saying that this is going to be perfect but we could change this to be like you could have the whole splash screen get passed in you could do I progress uh what's this need to be like a float or something maybe make it a double just for now but you could do something like this and then you have to right so we could go report the progress and it might just be uh I think this goes on a range of I actually can't remember how this thing works but you might be able to just go up by one or every iteration my goodness we want to go up to a Max of one so you could report a program ress update the value of the so I think this is the overall progress so if we wanted it from 0 to one for us we would want to do uh I I or right am I losing my why can't I do math right now yeah that's right because 10 would give us one so that's a way that you could do it but then we'd have to go down to here and we need to give it the progress which we don't have but you could go change it so your splash screen you could either have a progress reporter you could make this thing itself I generally don't like doing this kind of thing and I I'll show you what it looks like but I'll explain why I don't like doing it um so this now works except splash window over here needs this so I generally am not a huge fan this one is so simple that it doesn't make a big difference I don't like doing this kind of thing normally because I don't like building deeper hierarchies I know it's just an interface to slap onto this thing but we're now saying like that there's just more stuff that this thing has to do I'm just not a I'd rather personally I'd rather have smaller more purpose built classes but again just to make this super straightforward um let's go back to here where was the work sorry this part so this is kind of interesting because this is supposed to be done on a background task but if we want to report progress and show in the user interface what were we talking about earlier with the dispatcher right so this is coming from a background thread but if we want to go report progress and we want to show something on the user interface what are we going to do so let's go hack something up we're going to go put a text block uh wow amazing co-pilot is just lovely uh I'm going to cheat a little bit too um I'm breaking all of my rules just cuz there's not a lot of time left on the stream but we wouldn't be doing this kind of stuff with uh directly accessing the controls we would have view models for them so I'm trying to be very very explicit that I am breaking some of the rules that I like to have so if if we go back to here if someone were reporting this if we were to directly just go progress text block and do this oh what's P0 what is that is that a percent I never know my format strings I'm going to leave it because I think that's a percent with zero decimal places I think so if we go do this I think it will throw an exception because this is going to be on a background thread by the time it gets to us so let's go run it I was wrong it just works that's cool but our progress is weird right it's going up by 10% every time that makes sense we could go do this to make it more exciting so just for what it's worth I thought that the way this was working we were going to be on a background thread so why did it not blow up very interesting uh let's see well hold on is there a that's what I want let's run it again there's no name oh and our progress is out to lunch now sorry um yeah it needs to be this now I wasn't paying attention to that part sorry I was trying to look at the current thread part let's just put a break point here if we look oh sorry this uh computer doesn't have it set up I'm going to pull up the uh the threads window I just have to be able to read Windows threads so it is on the main thread so that's kind of risky actually I didn't didn't realize this um this all of this work that we're doing is technically on the main thread which is not what we want to do [Music] um so I think when we go to run this there's a way that you can do this better where when we go to run a task how does this need to look you can basically tell the scheduler like this is going to be a long running background task and it will prioritize putting it on a different thread um anyway to go back to I'm just thinking about the time constraints that I have here I'm not going to be able to go answer that for you guys sorry the point that I wanted to get across is right you need to ask this question before you go do this this is one of the biggest issues when we're dealing with this kind of stuff that's uh asynchronous work and user interfaces is we need to know the answer to this question because if we don't we're in for a world of pain but we have the solution for it right so you can do uh dispatcher yeah there we go I was hoping that it co-pilot would just pick up on exactly what I'm trying to do but apparently not all right so we have this if we're not on the main thread but like we just saw it is working but uh I think personally that something is not right with how this work is being done this should be done not on the main thread but we're not going to be able to get to that I don't think in the next little bit I want want to just make sure that we can kind of Step through this we'll make a list of what's outstanding and that way if you're watching this uh especially after it's been recorded and you're like okay like how did how did Nick get the splash screen to work we can just make sure that you have a uh a checklist of things to double check so at this point we can do a little bit of progress reporting if I go run this hopefully we see it counts up pretty quick right gets to 99% kind of weird and that's because this is from 0 to 100 so easy solution 100% right so that's good you can close it excellent so if you need progress reporting there you go uh something else to keep in mind I didn't mention this but this is a really itive way to do progress reporting it's a buil-in interface that we have access to you you might want to do something more robust for Progress reporting so for example instead of just having a number you might want to do um something that has like a status in it as well right so where was this thing defined so I did I progress double I think you can do this I'm just going to call it progress dto just for data transfer object just bear with me for a second so we can have a double value for the progress and then a string of message so you could do something like this and I meant to make this a record sorry I think you can do this and that would mean that we need to change a couple of other things so uh we could do let's see there we go co-pilot so creative so and it kind of messed up right I actually need this because it's off by one so I put the progress info here but this progress dto um if we go back over here sorry I'm jumping around here this was the other spot it needs to have this which means this needs to be here and that way we can do something a little bit more interesting so let's see uh can we what's there's a progress bar nice okay so we can have a progress bar and a progress text block so you could do something like um value. message come on co-pilot here we go that's kind of confusing progress info there we go so we could do something like this and combine them sorry let me collapse this because it's distracting me so here we're literally able to now pass in progress in terms of count right how far along we are and then some message this is obviously a very boring message right it's just saying which one we're doing but let's see oh no why doesn't that work that progress bar sucks that's a that is a window progress bar if I ever saw one um it's because I think here um the progress bar needs to have a Max and I think I just have to do that let's find out that's much better you're not waiting for forever for it to to happen so there we go a little bit of progress I actually wasn't planning to do progress on the splash screen but that's how you can tackle it um with about 20 minutes left I want to start wrapping up make sure there's any there's any questions I can answer them for people but the things that I want to address as we we're looking at I'm going to make my list let's do it above here okay so first thing um how to move away from the Splash Window um control and get to an abstract interface but the second part to this was should we be using a view model for the Splash Window instead of not what I wanted to say co-pilot instead of using the view interface directly so let's talk about these two things very briefly you will recall hopefully that I had I Splash went screen that's what I wanted to have here but we have to go deal with this stuff which I think is fine this isn't too hard to do right the this is basically just having an event on our view which is simple so just to prove it um Splash Window so window has let's see I just want to jump to the definition so I get the signature okay so we could literally go on our splash screen I like putting events above my methods just out of habit so that's cool we've already addressed one of them um I don't like I I don't want to go put this onto the The View interface and this is where I'm getting a little bit torn so I don't want to do that because for me this should be like this is very specific to WPF I think having a closing event handler is fine like that is something that in an abstract sense that could be on WPF that could be on Wind forms that that's a concept that applies to other things other than just WPF but this is literally a WPF specific thing so I would like to make it such that I don't have to to know that for my presenter it works right it works but that's why I'm just leaving this back as uh Splash Window for now because I'm going to put the fix me here should this be done through a view model with a binding and a converter okay so this together and maybe I'll copy this as well up to here so we want to move away from that control we want to get to the interface uh and then but this next part is like really how much view model versus The View do we want to deal with I mentioned way earlier in the Stream that when I'm passing in a view and using the interface so this would have been iash screen I only like using views if I'm trying to to literally compose what the user interface is going to look like stacking control and stuff together I don't like having access to the view to manipulate it in my opinion that's what the view model is for the bindings can take care of the rest but it leaves us in a weird State because the way that this is currently looking is I would also need like [Music] Splash slash view model and like now I have access to both of these things um to me that doesn't seem right but it also suggests to me that I don't need that Splash Window and I'm going to try to explain this I don't need the Splash Window because if I had a splash view model that was set up properly um like I would have instead of this it would be uh Slash viw model um. can right I'd have that and the other thing is like I wouldn't be hooking up directly to this views event I I want everything to go through the view model that's the point but it's kind of weird um because like I said I'm combining these two use cases so I apologize because I thought that on the Fly I would be able to figure this out um I like I mentioned before in other streams I spent a long time doing this stuff and having this work properly but it's been probably probably over four years since I've been doing WPF stuff and probably six years since I put together something like a splash screen so for now we have this going on it's not the end of the world like we showed earlier in the Stream it is functional this works so it's kind of hard to argue with working code uh especially if you understand the tradeoffs you're making and in our case if you're only building WPF like you're not really missing out on anything um the other thing that I wanted to call out in terms of things we could improve how can we pass in the dispatcher via dependency injection and if we go back that's this part right here this is pretty nasty um we want to make sure that we can pass this in and not pull it in if that makes sense uh to to explain why that's important I was talking about this presenter the goal this is kind of full circle before I sign off here the goal of the presenter was that if we have the presenter we have the right abstractions in here in order to go make this stuff very testable we don't need a WPF application we don't need to have the WPF controls shown so you're literally not launching a WPF app to go make this Splash presenter work when want to go test it yes some of the task delay stuff we'd have to go figure out there's solutions for that but we can make this very testable by moving away from WPF specific things because the way that I think about presenters is that they just don't care about the technology you're working with they care about the flow and the logic that you're trying to have so I would go build in business logic or workflow logic into these present and they just don't care if you're dealing with Wind forms WPF or anything else that's the goal that I have but the way that this is currently working is like this is a hard dependency on WPF specific stuff right it's literally saying if you want to go use this you need to go have a current application like that that doesn't feel good because if you're thinking about writing a unit test over this you have to go have an application that that feels gross to me um if you wanted to go write a unit test on this you need an application and you need a real whole main window we can't even mock this thing out so and then obviously I talked about the task stuff like for for delaying tasks you'd want to probably have something else uh other than this in place because makes it so you don't get a lot of control but the the point is that if the goal was to make all of this testable we're not quite there and that's why I think it's important to call this stuff out because I know there's solutions to this kind of thing because I've been doing that for years before I I moved over to Microsoft and and wasn't doing any more desktop development so I know it's doable and if you want to get to a point where this stuff is very testable I think we have to go address these things uh I should call out one more before I forget is the heavy or work call back actually so is it I don't think it is can we force it to run on the background another way just to mention it is instead of using a task to go do that you could literally go use a background worker it's a class right we can go do that my goodness come on worker uh do work you can hook up an event to it no that's not what I wanted co-pilot was fighting with visual studio so if I press tab what should it do should it go make the event or should it go do the co-pilot change and it's uh taking the visual studio suggestion before co-pilot but anyway you could go use a background worker and like conceptually I thought the task stuff was going to be a lot more obvious but clearly not uh because we saw that the background work was in fact happening on the main thread right we saw this work is not being done on the right thread so if we used a background worker you could go do this the same way and maybe we got 10 minutes left can we make that happen let's see um what I might want to do instead is where are we running that we have this do heavy work task I don't know um okay let's see let's see if we can do it if I made a background worker and then background work and and I should call out to I'm about to go Rush this in a few minutes but a background worker does have uh you can see that it has progress reporting and stuff built in so we could change our API to go past this along instead but you're about to see me try and Rush this in a couple minutes so background worker it has a do work method uh sender e okay what I wanted to do was basically this oh Shawn might save the day come on Shawn let's see it nice thank you okay so yes I think you're you're right this is a with reference to the dispatcher folks um so if we go back up here I think what Sean's saying is absolutely right what's tricky is that my goal was to have screw door load everything automatically and I don't think we're going to have that so I like doing this pattern because it will just automatically go find and register everything it needs to but it's going to break down so I think what we do want to have is application. dis current. dispatcher here and can we simplify this nice and can we simplify this nice and I don't think we want that we want dispatch and that means hopefully thank you very much Sean for checking that out let me comment this out just in case it's crunch time I got to start working less than seven minutes okay so I broke probably this stuff down here we're going to try and do two birds with one stone though so there we go this should go run it on a background thread now it better it's going to mean that our progress reporting needs to have this stuff okay so this is forcing it to run on the main thread when we report the progress because this stuff better be done on a background thread now um and do we need we need to wait for the background worker to finish oh what's a good way to do this SE semi for slim wait this is this is something I got to put the semaphore above okay this actually might block the thread we're going to see some weird stuff happening here so this might might not work I'll revert it if it doesn't CU I want to see if the dispatcher at least works I was just trying to see if we could hack together getting a background worker to make all this stuff happen um I am feeling like that's not going to be the case is it release I want I thought there was yeah maybe okay let's see never works the first time right ah doesn't work and I think we probably made a deadlock I think this thing here who someone was joking with me they said on LinkedIn they said I want to see you have a deadlock like go code that and I was like I guarantee you I'll do it without trying um I think that's what happened here or is it because I didn't start it I think it's cuz I didn't start it okay maybe no deadlock let's go so far so good rocking and rolling no way it's going to work boom we did it in like four minutes we fixed two of these things we did it thread sleep house with things like that yeah okay so we got the dependency injection working thank you very much Sean um can even clean that up a little bit more so we can forcefully add the Singleton on for the dispatcher that means that our dependency container can now go resolve it so um that's number three off the list is the heavy work callback actually running on the right thread now is so we fix that one too clean this up we got 4 minutes left before I got a sign off um this is nasty so for anyone who's watching this and they're like dude what the heck did you just do um I just combine two different concepts together so really this do work like we should if we're going to go with a background worker we should go fully with the background worker I'm literally doing a hybrid so um just to call it out that's why this looks so disgusting but to explain what's happening here because I rush through it very quickly is we have a event handler that's just going to say when the background worker needs to do work and this is going to run on a background thread just go run this call back that we had before that's all that's happening here run worker completed is an event handler that runs when this thing is done and I believe run worker completed does happen on the main thread in case you're curious so when this thing's done we're saying hey go finish and Trigger this semaphor so we can move past and I should go run this one more time and make sure I can move the window around and I can so this all this all works it's just kind of nasty hold on did I close it this is wrong we we did break it this is why we need our tests in place pay pay close attention because I think I have my semaphore wrong does this fix it okay there is the deadlock this background worker stuff doesn't work sorry that this was a bit of a roller Co coaster rate at the end of The Stream So as promised on LinkedIn here's the deadlock the reason this is all busted and janky is because I had this semaphor set like this Watch What Happens though it's going to go right past see it's setting it's basically just going through the whole thing right away and I notied that because when I go to here I can clo um I slept for too long I can close it right away and that's not what we want so in fact we do want to not have that going on this is not right and we do want to keep this and we still have that other fix me then we have to make sure that we can make this happen on the right thread so with less than 60 seconds left sorry for the roller coaster at least Shawn was very helpful getting the dispatch onto the container this is what we need right I can't close it now I can and folks that is how you rush through making a splash screen I hope that was helpful thanks for sticking through some of the gotchas there thanks chat for chiming in and Pa programming uh greatly appreciated and yeah I am hoping that over the weekend I'll get one more of these in and if not please join me on Monday night 900 p.m. PST it won't be coding but it's General software engineering so hope to see you there thanks and have an awesome weekend take care

Frequently Asked Questions

What is the purpose of a splash screen in a WPF application?

The purpose of a splash screen in a WPF application is to provide a visual distraction to the user while the application is loading in the background. It can also give users an indication that the application is not frozen and is actively loading data.

How can I dismiss the splash screen before the configured time is up?

You can dismiss the splash screen early by implementing a click event on the splash screen itself. This allows users to close the splash screen if they feel it's been displayed long enough, as long as the background loading is still in progress.

What are some best practices for implementing a splash screen in WPF?

Some best practices for implementing a splash screen in WPF include ensuring that it can be dismissed early, supporting background loading of application data, and providing some form of progress indication to the user. Additionally, it's important to manage threading correctly to avoid freezing the user interface.

These FAQs were generated by AI from the video transcript.
An error has occurred. This application may no longer respond until reloaded. Reload