Event Aggregation in WPF - A TimCo Retail Manager Video

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome to another video in the timko retail manager course this course focuses on real-world application development right now we're working on building our first section of work which is a basic cash register in this video we're going to wire up the event aggregator and now what that's gonna do is allow us to have some inter forum communication now if you're a patreon supporter the $5 per month level or higher make sure you head over to get the latest source code either way make sure you hit that subscribe button and a little bell to notify you so you can follow along and finally as you think of suggestions please leave them down the comments I want to hear your thoughts on this course in fact we're gonna start off this video not by doing anything aggregation by fixing some some bugs we have instead okay so there's a couple of comments they got after the last video that we're really helpful and we're gonna go ahead and implement those right away just kind of clean some things up okay so please let me know what you see in these videos what you want changed what you have suggestions for for the future I put on a list we we've I looked through them I think about them and I may even ask for some feedback from them as well before you actually put them in place okay so with that being said let's get started so I have opened the project if we go to teen Explorer there's no changes here and if we go a sync and do the fetch there's doing no changes on the server either so are good to go now the first thing we're going to do is we're going to kind of go back over we did last time because there's some changes to be made specifically in the sales view model there's a couple of issues the first issue is in item quantity we have notify have property change for products not for quietiy the reason why we have it for products is because it's a copy paste error so in my haste to redo it or do new ones quickly I just went up to products I said copy I came down here and said paste and forgot to change it that's why I am leery of ever encouraging or even showing copying and pasting because this is what happens this was not a bug where something doesn't work and get a red squiggly those are obvious and they're quick to be a fix but in this case it's a lot more subtle because I copied working coat so since I copied working code it still works it's just not doing what I expect it to do that means that I don't catch this or in fact I didn't catch us so if you didn't catch it then what would happen is this a good production and only in production I find out something's not quite right and at that point I'd you know go through code and find out why and then issue a patch and it's just it's messy so copying and pasting can be bad you need to make sure that when you copy and paste you're really careful to be detail-oriented read through all the code now to skim it so the fix for this is to say it's actually item quantity not the products okay so that that's one and then next one is one that's more of a it's still on item quantity but it's more of a way that Caliburn micro especially handles different types so I did string because if we notice over here in sales view this quantity is a is a text box so it makes sense that's gonna return text but what we can do in calibre and micro is say actually I want this to be an int and to change the backing field well and that works what's gonna happen now is a little bit of validation actually happens right away so the user types in something like test in the quantity box it's gonna outline this box in red and say no that's not a valid value but if you put one two three four in there that's fine and it's going to be a valid value and allow it so even though it's a text box we can we can have the the wired-up property be a different type and we'll do that conversion for us and validate to make sure that it is valid data that's going in okay so that's a really handy little tool to have so that's another suggestion that came from the comments I really appreciate it so those are the two that I had that I thought we need to do in this video there's a whole run suggestion list of other things that we should probably address at some point I know that came up that will address in the future is for login page we use the the email address for the username so email address and password which is great because typically one person has one I'm sorry one email address associated with one person meaning I have multiple email addresses but they're only mine okay so I don't have I don't share one with somebody else now occasionally that's not true but for login purposes usually you have that one email address that you control that's just for you and that's what you use the problem is the email addresses change whether I you know for example my my grandmother had an email address with her Internet service provider so it was you know as her handle at the Internet Service Providers address the problem is she moved and when she moved she doesn't have that Internet service provider anymore her email address changed the example I believe in the comments was a school that changes students email addresses to also include the year they graduate in there that our handle portion well now that all those log names have to change so where I get to that in the future but I wanna let you know that these are really valuable comments they're on the list and we'll definitely address them at some point but some of them like these really should be addressed right away okay so that's enough set up and talk about other stuff let's get into event aggregation so the idea here is that we have the the shell view kind of holds everything that's our container for everything and then initially it opens up the login form but when they hit login we want to have happen is that it close the login form and it opened up the sales page that's what the ideal is so how do we do that because the shell view has to know about the login event and if it worked or not and so on well the way we do that is we broadcast the entire WPF application here's a new event and then anybody listening for that specific event can then act upon it okay so we're gonna do is when the login page the login button is clicked and it successfully logs a user in we're gonna broadcast an event that says hey someone just logged in now if that happens the shell view is gonna listen for that event and say okay since sone is logged in I can close the login button or login page and I can create I can open up an instance of the sales page so that's what we're going to do there's a little more complexity to it because we have to also close out and can't refresh that login page so you don't save those credentials accidentally okay so let's go ahead and get started the place the star is actually in bootstrapper so bootstrappers where we accept things a long time ago it seems like at least in this course so we set up bootstrapper and this is where we configure the container and we brought in all the view models and sets them on startup things like the shell view model is what starts okay so these are all the things we configure way back way well one of the things we've added is we add this event aggregator now this was something that's built into calibre and micro and this is one of the reasons why I like calibre micro is that it is somewhat opinionated meaning it has an idea of what is best and tries to point you in that direction some people don't like opinions in their frameworks they like to have the poll things in whatever or they want or whatever type they want and you kind of mix and match I prefer to have some opinions in my framework like this is the event system you'll use this is the window manager system you use and so on because well even the the container type or the yeah the container so those are kind of things I like to have opinions on because then first of all I know it's gonna work with my framework second of all when it comes to documentation they're going to document what they have opinions on and so I know the more documentation for that then for something else and third of all it just makes it easier I don't have to make a decision about what depends the injection system to use or what event irrigation system to use or even you'll find those and have 18 different moving pieces with caliber and micro it just brings in these basic things you're gonna need and says if you want them they're already here so in our case we already brought it in we knew every I need at some point we just haven't used it yet so we're going to do actually use this I event aggregator to pull in that wherever we need it the first place we need it is in the log in view model so we're gonna bring it in right here and call events and this again is a beauty of dependency injection is that I didn't have to know how to instantiate it I didn't have a know how to set up nothing I said you know what I want it give it to me and now I have it okay so now I'm gonna use it in anywhere in this class so I'm gonna do is I am going to come down to our login and right afterwards I'm gonna raise an event and the events gonna say hey someone logged in that's all it's gonna be so I'm gonna say events dot and I have a few options here but the option I want is this publish down here there's actually a few of them there's publish publish on background thread on current thread on UI thread and UI thread a sync the one I want is published on UI thread what it's gonna do is make sure that if this word have slipped off the UI thread and gone to a background thread for some reason that I'm doubly sure that the event will be listened to on the user interface thread that means that other UI's can use it without having any kind of cross threading issues okay so it's already baked in order to say is published on UI thread and what I publish something and this something it could be a string like so but the problem there is that's way too generic you don't know what that string represents so a lot of people may be looking for a string so instead we can do in public a class instance and then we'll say okay does anybody look for that class and if so we can pass that instance in so we're gonna do is we're going to create some class event classes so on my desktop UI project I'm going to right-click and say add a folder I'm gonna say event models inside here I'm gonna right click and say add class and I call this class the logged on event my got public now here's the what seemed like a weird thing I don't have to put any properties methods or events inside this class in fact at this point I don't think I need to so I can do here is say new vlog on event actually reading that event model so let's do that now it used to be if you renamed it over here on the right and it would pop up box saying do you want reading it on the left as well if the actual class but now you can say just rename it in the class and then control dot and one of the options is to rename the file to logon event model notice over here on the right the long eye event if I hit enter now it changes to logon event model okay now the one that didn't do then is it didn't also rename it so notice over here new long event in the event model okay so I'm gonna publish and say pass in a logon event model which is empty there's nothing in it so why would I do that why did I create an empty class for an event well the reason why is because that then differentiates it from other calls and it's very obvious that this is a logon event model so you know exactly what what's doing what it's for so in this case it's it's the the logon event it's not the log off event it's not the you know I almost crashed the computer event it's not the error event it's not anything else it's the log on event model so when we're subscribing to this we're subscribing just to logon events not to every type of event okay so we don't have to pass idea there's no data to pass we could you know kind of fudge it up and and pass data across that we could say mail pass the user name and password but that doesn't make sense because right up here they get logged in user info if we control f12 to the implementation just to show you that by quick this is actually an interface so see I API helper if you hit f12 it goes to the interface but if you control f12 it goes to the implementation if it can find it but in this case of course it can so this is what's happening we're loading this logged in user which we can get from the the dependency injection system so wherever we need to login user information we just ask for it and that's a singleton so that whenever you update in one spot it's updated everywhere already so we don't have to pass in this information this information right down here because we already have it so it's not a point to doing it that way I don't want to try and confuse matters by having information in two different spots and one might become outdated and that's not good idea so this way we're just saying hey a new login event happened no information necessary so that's all there is to the broadcast side just take that event aggregator and say publish on UI thread since this is a UI thing and we're just saying log on event that's it okay no other changes besides bringing in the event I event aggregator and storing it longer-term okay so now we've got the yes we logged on event now let's go the other side of things let's close these out let's go the other side which is the shell view model and the shell view model we want to listen for that event and that takes a couple of steps first of all up here in our shell view model we have it inherits from conductor but then we also want to implement an eye handle and why I handle the log on event model and control dot for that so this is pretty cool now that's control dot first of all to implement that interface that adds one method called handle and we'll get to that in a minute but I love house is named and this is why good naming is really important and I also believe valuable what do you think this interface does it handles the logon event model now you could call it log on an event and maybe you should and I'm trying to bait in that because if we call it log on the event that makes it even more readable but log on the event kind of indicates that might have information inside of it I think I think I kind of want to have it be log on event after all can I go back it a fourth but let's do this log on event control dot let's rename everywhere first and then control dot again and rename that file so the own that order it works if you just can't do in the opposite order okay so I handle the logon event that reads great you know exactly what is doing so what happens was a logon event well when we handle a logon event it calls the handle method and it passes in that logon event object now in this case we want to care about the object because it's empty but we can do stuff in here like close out that login form open up the sales view view now if we just did just this and we put some code in here it wouldn't work quite yet and the reason why is because there's another piece to handling events so we've said we handle long an offense but we also have to register that we listen for log for events at all ok so there's there's two pieces to it so now I need to bring in just let me do the log in view model we brought in as I event aggregator not copy and paste it in right here and then do kind of the same thing at before where I once I clean us up and we'll wire it up like so so now I have that event aggregator what I can do is say underscore events dot subscribe so I'm subscribing to events and saying well who's subscribing to events and almost always you guys say well I am or this this represents the current instance of this class whatever instance you're right now in and the reason why you have to tell it who is subscribing is because it has the event aggregator has to say okay I'm remembering who's subscribing so that when an event happens I'm going to send that event to every subscriber even if they're not listening for that particular type okay there's gonna broadcast down and it's gonna look and say well the shell viewmodel listen for let's say I handle string nope so don't set it down but then the next event comes along and says you know okay the shell viewmodel listen for logon event well yes it does so therefore call shell view model dot handle it's overloaded for that particular type logon event and set call that method so that's what's gonna happen and that's the two pieces on the subscribers side do you have to do one you actually to handle the event type you're listening for if you have multiple you just keep having multiple lists out here remember you can have as many interfaces as you want now and let's just show it real quick I handle string if you can create string event a control dot and now notice I have a second handle event this one for string so that's how you that's what I have to do for implementing multiple so that's part one have the handler specify what events you're listening for part two is to subscribe to events in general okay so now we have an event that's going to fire whenever we log in and that's successful login so right down here at the bottom we log in we're a wait for this to be done if there's any problems it goes the catch it never hits this line down here but if there is no problems it will get to the this line right here that says publishing the UI thread a new logon event and with that this we get triggered so now what we do in here well we have a few options so the first thing I want to do is I want to close out that event which we are the close of that forum which really isn't much of anything it's just let's just activate a new forum well the new forum is going to be the the sales view model so let's bring that in sales view model of call it sales VM and I'll copy that and then we'll bring it in let's let's do this let's move things around a little bit and I want to whoops want to bring in that sales vm2 and then down here we can say is activate item sales vm so when we we log in it's going to essentially close out the login view and open up the sales view the reason that I say essentially is because you can only have one item active at a time when you have this conductor okay notice right here mounts over it says an implementation that holds on to it activates only one item at a time so that's what I do now that doesn't destroy the login view model because we're still holding on to that instance here the problem there is if we were to open back up the login view it would have that username and password it's still there and any other properties that are set behind scenes now I could try to you know look at that view model and and its modified or clear out the data but that seems less than ideal even if I miss something or if I add something later that's sensitive and I forget to also add to the clear out event what I'm gonna do instead is going to create a new instance of the login view model and use that throughout the system or throughout this first page okay so to create a new instance of it but how I do that it's it not really good idea to say equals new login view model that's not how dependency injection systems work so what we're gonna do instead is we're going to go back to the bootstrapper and look at this simple container this simple container we actually add to itself so if we ask for a simple container we'll get this container and the reason why this is important is because we can then in our dependency injection system let's just hit enter here and say simple container container and then we can capture this up here like so and then we can let's just before I forget then we can do is we can actually UPS me a comma here we can request new instances whatever we want so we can say after this view model has been updated we can override the current login view model so login V M equals container dot get instance of type login view model well that I'll do is get a new instance of it and place it into our login via so that kind of wipes out that that login VM so that whenever we need a future it's clean and fresh and does not have any sensitive information in it now you may have noticed the immediate grumbling already this is a lot of stuff in our constructor and you know what yeah it is but it's not really hurting anything by the same time maybe it's not ideal for this particular form because this form or this view model controls all the other views in the system and sometimes it doesn't seem like we need to have all this we can just say you know what just ask for the container and then do this for any type we want without doing the the store up here the private variable and so on and yes we can do that so we don't have to ask for every form or every item even we can just get it when we need it but there's a downside of that and here's the downside the sales via let's just say we started entering information on a checkout page so we've added three things to the cart and we go oh you know what I need to go a different form for some reason let's just say they want to sign for our our frequent shopper card so you pull up a new form that's the frequent shopper card signup form and we we fill in the information and we hit submit and then you go back and say we know what container get me an instance of the shopping cart again and or a sales view model and they do and it's blank because it's not a singleton so we just lost all of their their cart all our information and that's not ideal whereas if we already have that instance we can come back to it multiple times and the cart stays where we left it okay so the basket is half folded the baskets half full when it come back so that's that's the other end of it is that that might be we want to do for some things so I think that the way to cut down some of this is we can get rid of asking fill login VM we can get rid of storing a login VM we can get rid of wiring the login VM and once we copy this we can get rid of this last well instead we activate item we can just immediately ask for an instance of a login view model that way it's fresh every single time because the log the view models are not Singleton's they're per request meaning every time you request it it gets a new instance of it therefore whenever we stop using this we deactivate the login view will go away so it will never have data from a previous call which is actually ideal for a login form we don't want that data be stored accidentally so this actually makes it a little simpler and reduces the number of things we're passing in here but the same time I'm not gonna do that for the sales view and the event aggregator all of that one is up for debate probably I do think that I might use it in the future to also broadcast events not just subscribe to events so I'll leave that one the way it is so it's kind of balanced you want to hit is do you want it the life of this instance or do you want it for a new instance every time that you want to load it and different forms will have different answers or maybe different circumstances will have a same form have different answers so it really is dependent on your situation not just one blanket this is how you do it all right so let's see it's an action see how we do it's gonna launch this right launches two things it launches the API which is right here and also launches the it also launches the DPF login form so let's put our username and password in login and you went right to the sales page that cool now a sales page is cut off honestly that it's not quite tall enough here and notice no matter how you move this there's not enough space over here there's a little bit of space not enough so we're gonna do it around move the spacing over and give it more space on the left and our right and the bottom the top I think is fine I think it's fine where it's at right now so that's what we'll do I'll also make this form a little bigger because you know that's not quite big enough let me get a little bigger okay so once that stopped if it's not both of those by the way in order to stop this or is hit the red button let's go to the shell view and we'll change the height and width this is the starter height so let's change the 550 IMATS mater around 600 600 and the width let's make a thousand now again the user can can shrink this that they want and that's fine boards kind of given a suggested starting view you wanted to look good when it starts so that's why we're saying at these parameters so do that and the other thing is you want some more spacing now right now if you look at the content control we have a margin of five all around which is why you had a little bit of space but not much more instead what I'm going to do is put 20 on the left I'm gonna put five on top because five on top is fine and then 20 on the right and 20 on the bottom notice that that blue box here kind of indicates where things layout and that should solve the spacing issue let's start this up again and see we get there's the API there's our login form it didn't really change the login form because the login form is designed to be centered so T Cory at I am Tim Cory comm and our password super secret PWD 1 2 3 4 5 . hit login ha ha I typed it wrong oh you know why it's not t Cory it's Tim I have something email addresses login there we go so now I can see the whole sales page these items the car items in the cart will expand this horizontally because they'll get larger as the the width of items inside them get larger which is what you want to a PF ado to grow and shrink as needed so we have some good spacing over here so that's good alright so I think that's where we should stop right now we've got the sales page coming up we've got the login form working aware of it if it correctly logs in then it closes out and it takes us to the sales page we've got the event irrigation system in place so that if we have any other events we want to listen to in other places we can do so and I think we're set now for the next step which be the next video and that is I want to bring some data from a database all the way in populate this items list so we can start wiring up this sales page and actually have it do something or it gets the point where I'm not sure if it's being next video or the video afterwards but where this this this sales page actually does something where you can select something give it a quantity add to the cart remove things in the cart and have these calculate so that's coming but the the first things coming up is just populating data here which will have to put some data in our database just kind of dummy data but actually populating data here so we can start working with it on the sales page okay but until then thanks for watching as always I am Tim quarry [Music] you [Music]
Info
Channel: IAmTimCorey
Views: 20,995
Rating: undefined out of 5
Keywords: .net, C#, Visual Studio, code, programming, tutorial, course, training, how to, tim corey, C# course, C# training, C# tutorial, C# app start to finish, timco, timco retail manager, wpf, asp.net, .net core, asp.net mvc, autofac, c# solid, c# solid principles, dependency injection, tdd, unit testing, xunit, moq
Id: 70Dj9cnyu2g
Channel Id: undefined
Length: 38min 29sec (2309 seconds)
Published: Mon Apr 15 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.