C# WPF UI Tutorials: 11 - Dependency Injection & Multiple Projects

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] so we're carrying on from the video last week where the peseta would and before we go ahead I'm going to do something I don't often do let's install a few extensions into Visual Studio I don't like adding third-party things to Visual Studio because it slows it down you've become reliant on them things like that so I rarely use any kind of add-ins to visual studio but they've recently released some new productivity power tools they're basically a group of you know really popular commands and the ones I've highlighted in red here I'm going to use so copy HTML we just open it up basically whenever you copy code and if you pasting it into something that only accepts HTML like a web page it will actually paste us all the colors so it looks just like the code so that's going to be helpful for just general copy and paste and the amount of times your copy it's not going to slow anything down so I'm going to put that one on I've already installed that this one's going to be really useful for these videos I'm hoping I haven't tried it yet but double click to maximize our window so we should be able to just double click a code window and have it completely full screen and then just double click or escape or whatever it is to get out of it again so we'll try this in a moment so all you do is click download and I'll install the last one so you can see fix mixed tabs again I work with multiple developers some of them are there Visual Studio setup for tabs others have it for spaces some people are just bad at maintaining the accurate you know distance between indentations so this little add-on made by Microsoft is going to be nicely efficient every time you've got a file open if any inconsistency in the tabs or the spaces you'll get a little bar at the top that gives you the option to fix those so again pretty lightweight so I'm going to install that one and the last one is power commands for visual studio so I'm going to have install this one this time to show you and the reason I wanted this one was because of this remove and sort using zhan save I'm potentially thinking at using I'm not underplaying convinced yet because I don't really like things messing any files when I click save I expect them to be what they are but there's quite a lot of commands in here that are useful like adding project file now is like a shortcut for non Net commands and unload all projects and there's just quite a lot of useful little commands and they don't do anything unless you run them so again the like you can see here power commands and then you know you just want to filter all of your unused namespaces and things like that or copy the path to the file there's just a few things in there I think will be useful so to install these add-ins you just click the download button and you can do this inside a visual studio but I've just done it on the marketplace top visual studio comm and search for power power tools 2017 was the original page and then it takes you to these specific ones you pop up with this open dialog just open it that's fine and then what it will do is try and install into Visual Studio make sure Visual Studio is closed otherwise it'll just ask you to close it and then click install and then it will just add this extension and you can always remove them if you don't like them so that's the extension done will show you those in a second the next thing I've changed my keyboard in case people asked yeah I know a lot of you like their keyboards so this is one of just change - it's a MX brown keys now so it's mechanical you can hear the slight difference in the keys I'm guessing there's a little bit quieter which I thought was the other keyboard seemed a little bit too loud so let's go ahead and open visual studio now and let's get started so the first time you open after installing new extensions you get this writing component cache that's basically setting up there the new extensions and then here we are let's open up the set a word and those extensions now we go to tools extensions and updates' at the top you'll see now they're in this installed or they should be does the copy HTML so you could just don't install if you liked double-click maximize fix tabs and power tools power commands there so they're in there you want to remove them or disable them so let's try first make this but 270 minimize this a mess and now I should be able to just guess double click here oh yeah oh that kind of didn't work let's try that again just double click again huh yes Hudson work very well opens and closes let's try this one okay so code files work I've got to submit a bug for them then in that case how do we get out and minimized you just drag I guess so work profiles like this and then it looks like you just click and drag double-click the bar it's maximized and click and drag base and it instantly redox the thing it doesn't look like it works or is there's a more files which typical is the one we use a lot of so you double click as a more CS file oh now it's working ok that must've been just a little bit glitchy I don't know so it's the zamel itself isn't it so this is Armel file which is under it was to do with the split screen swap them over minimize that and double click yes I think it works now so it's a little bit finicky you have to make sure you haven't got both open I guess and then it doesn't redock quite right so it does a little bit buggy there so we'll maybe avoid using that for the zamel files and I'll submit an initial bug anyway the other thing you'll have noticed I've changed only windows to complete darkness so all the files and everything and I doc interestingly that's caused us to notice an issue in pages let's say the login page which we are on splits swap over and where are we and then look what's happened so because now my window and the same thing with like notepad as you noticed that the background of everything is now dark gray and text and light because we've explicitly set like the placeholder color has black we've never explicitly set the background color or foreground color of the text box so if we run this I think automatically change that to run let's just change it to the page control t brings up this new little search dialog let's type in window view model and press ENTER and then public properties change the start of page to login and then at 5:00 and let's take a look at that again and you'll see the scroll bar that we haven't styled yet has come to dark as well and then these you can see a darker when you type the basically following my Windows machines color which is okay but not when we've customized you know our UI to be what we want it to look like so I think one thing in light of this is we should make a theme for our own application that's also dark so you've got a light and a dark version but for now we need to at least fix this issue so let's start with that that's a nice easy one yeah this is now I think I might on and still like double-click things as much as it look beautiful I don't think that's really working that well let me just disable it for now or a shame that looked like it was going to be useful this is why I don't tend to do [Music] extensions and items they just rarely work you know as clean as the entire visual studio rather than slots open styles for the text box or texts in this case is the text box style already grab I add a property for in the background to be foreground light brush which is the white and the foreground wants to be the foreground dark brush which is our text color same for the password box so just find the password box paste that in as well and then press f5 I think I should fix the text boxes there we go so kind of well not to be darker so that's what the dark was I'm a very dark wanted text box very dark try that once more there we go so that's back to working well style this scroll bar another time so we were going to do while I was going to do the chat bubbles for the chat page and I've had a lot of people wanting to progress their own applications and now they get at the point where you've got a sign-in page well how do I now load a register page or how to are loading on the page when I click buttons and that's or how do I change the side menu so a lot of these questions now are starting to go a little bit forward of the video which is fine but that also means we need to step back and we really need to split this project now into its master and a core project because it's starting to grow large we also don't want these view models to be in you know the actual WPF application it's time to really clean up this project and we're also at the stage now let's let's basically play through this scenario and you'll see where we get to and why so we want to add a register page so let's start with that it's copy the login page copy and paste rename this to register page clean up the names split all right that so titled call it logically don't see the title in this one but we'll call it that register page as seven to get to the code behind this is also register page we don't care right now about the login view model we're not going to use this as you know we're not finishing this page in this tutorial so we just want to get the page up and running so there's a new class that will have to change the view model afterwards but it's perfectly valid vegies to class now change this text a little bit to sign up I know we'd want a password verification as well but again just for quickness we're looking all that for the moment change this to register and change this comment too or I already have an account and then we can click that to go to the login page we open up the login page and they've got sign-in a login and then this message is wrong this wants to be or create a free account and there's the new message so in order to get to the next page this would be the link that take you to the register page so let's start with putting those onto fresh lines now you have seen with the login button all you do to perform an action you know do something when the user clicks are on a button in this case which is bind to the command this allows your command you want to bind and we'll call this register command remember this is bound to the login view model so control t login view model enter we want to go to the commands copy and paste this and let's add a register command we name this and again commands are just basically functions of your will methods things to run button view model terms and then in the constructor create the commands we need to create the register command this time it's just a normal real a command we don't need to pass any parameter in like we did with the login and that will now just become stay async it always be a function called register that will make and then just make a new function copy and paste this again being a little bit lazy today a lot of copy and pasting attempt to basically use around takes the user to the register page there's no parameter called register get rid of the parameter we run a command we don't really need a command well yeah we could actually lock the login is running now I system well see this is not going to be instant in terms of change over when we animate but I think we don't need any sort of state we don't need to know when we're about to go to the register page because animating outers we're doing that so there's no need for a run command in this case so we've removed that this was all temporary code so right now this is at the point where to do go to register page and of course we haven't done anything so let's just wait I think the best way of doing this just a way to delay for one just to get rid of the error this is also needs to be ended in the name a sink so the other thing you'll notice I've added a config file to really force straight again more for our work in a environment with multiple developers and everybody's got a different style I like to keep the style specific so I've created we go to my overall git repository co-creator editor configs you open this in code this is a new thing for Visual Studio editor config isn't new it's a thing but it's now supported in Visual Studio 2017 and as you can see I've styled everything with these specific names like avoid this four methods field events and properties so that's why this is complaining that name can be simplified you don't need this because login is running if we look where this is than our public properties here so there's no need to put this dot in front of it this is where I used to like doing but analysis change my mind it's a redundant piece of you know writing that you don't need text you don't need so the reason that's red is because I've got this editor config file in the master directory where this is a child of and I've set this up so for fields methods in this case it was this properties one I want to say don't have this and I want it to show us an error in Visual Studio and I basically ever everything out of like forced this my styling convention throughout the entire application and the same with like login you'll see it says name rule violation missing suffix async so what happens when you get more people working on code and you code grows as well you can have synchronous functions like this that's just you call it there's no e as you call that command it runs and then you've got things that we turn tasks and they can be awaited so if you don't await them like here you've awaited a delay then after here if you then do something else you know in I want our I rather equals one say if we waited a thousand here this on now run the register function it'll wait for a second then it do whatever code you got if you remove the await then it's now going to tell you for one that it's not awaited so this is going to run completely separate and this will hit straightaway while that's still waiting but the issue comes not necessarily when some people might turn these squiggly lines off and other times it's just sometimes not obvious that you want to await something know they need to waiting so what I've started doing is enforcing that anything that returns a task ends with the name async so you'll see that as a naming rule down here I made somewhere here and it basically states that required suffix as async if the method has a sink in it so you don't need to understand this that is something separate but I'm just letting you know you know why I've now got these warnings have you all these errors so I'm going to go ahead and rename that login control RR and end it with async so now it's really obvious this method as asynchronous like there so now if we were to say remove this async and we remove that it's you know it's going to highlight and green there but that might not always happen people might turn that off but it's really obvious you've got the word async there so you know there should be a weight before it so that's the reason why I've put a sink after there and then we'll clear up this so a little bit of sidetrack there but again I always try to keep things clean and I'm always you know improving on it and changing things so that was that so back to where we were so now we're at the register page and put that back in a second so the first question is how do we change pages well in this case we have the main window I think yep main window we go down has a frame as we know here and this frame is bound to the current page of the view model which is the app view model right now now the window is view mirela and then we use a converter application page value converter so application page value converter which converts the page to this page so to change the page we need to change the application so the window view model we need to change this current page here as we do to change the page so you can do that one way so the quick way just to test that what we're doing works let's register page and this is where we're going to move into dependency injection in a moment and you'll see why and we're also going to split this project into a core and a WPF so it's going to be a lot of cleanup but you'll see why we're doing that in a moment so you're at the register you're in the login view model you now want to change to the register page so we're in one part of code in this view model so how do we now get back to the main window to the frame to the current page so effectively the data context of the window which we set up simply here as a view model so we need to get the main window then we need to get to the data context we need to cast it to all windows view more lemony to change the current page and as you can guess that's clearly not what we're going to end up doing but in order to do that we have application dot current main window which is named the same as ours but isn't the same thing this means gets the main window of the application so this will get us a window we need to cast it to our known type which is main window because we know that's what our window is a little bit confusing that it's called the same thing main window but that's just a property this is our class name this could have been called any other name so don't get that confused this is this will always return the main window of the application regardless if it wasn't called main window it just happens that we've called ours main window so this statement will get this window now in this window we need to get it data context in order to get the view model that is bound to so we then do start data context which is again just an object it doesn't know what it is we need to cast that so we'll cast that over here again that we know is a window view model and then we need to wrap that up again and now we can finally get to the current page and we can change that too and then we need to also add the register page here so let's just add another page the register page and then because we've done that we need the application page value converter to also create as a new page of register when we do that so that will now create the register page this will change the page now to the register page and that will actually then change pages I should do because press f5 and let's at least prove that we've changed a page and then you know how you technically do it so we click that and it's changed to as you can see the signup page and then we obviously can't you've now also see this navigation bar that by default has appeared because we're inside a frame so you can actually use this now to go back and forward between your pages you could also style this and you see my dark themes a little bit messed up there you can style this custom so it looks nice and you keep it and then you've got a little navigation bar a top book will decide on that later but you can see that's now navigated the page when we click that it goes ahead and so in fact it did it's now no longer ah there's another thing with that navigate paid this isn't bound to our view model so it's still things from the register page your moment not so we'd have to bind the navigation service to that but in general that's where we are we we now run the application this code runs and we can change from a sign-in to the signup and again we'll fix this animation afterwards so that's how you navigate but now another issue here is this code is growing all this needs to be shared this could be you know this application will grow it's going to get huge you don't just want it all in one project we need to split this out to multiple projects and view models are going to be in the base project so that they can be reused throughout different versions say the Android application or the iOS application so this view model room right now when we move it out to the core this won't even have access to this because this is WPF so we wouldn't be able to even do this in order get the data context in order to change the page and this is also a really bad way of doing it this is leaving the control of how you get the data in the hands of the caller here so this is one issue for one it's only and this is a question that a lot of you brought up many times was well how do I do this how do I access that how do I change the side menu and you can have the same issue all throughout you like well there's the side menu so this is right now just a side menu control on a main window in the application with no name so right now you can't access that you need to give it a name then you can access it but then you're back to accessing it that's really bad way all you're talking about then calling a function like this register that needs to be passed in the window view model is a variable sort of like you know window view model your model is so it's it's going to start getting messy so the solution to this hopefully now you've seen the problem the problem is you know accessing different parts of your application from other parts so let's start let's leave everything as it is and let's start by creating a new project first so this is the windows the peseta that word project the main one the WPF application right click on your solution ad we want the new project and we want a class library so dotnet framework in this case we're already in the facetted woods source folder so let's just open that up and you can see right now the solution is here and then you've got the facet word which is the project inside so if we now add this new class library we call it processo dot word cool click OK it's created as a new class library which compiles to a dll file and now you can see it's added this new folder inside there we've got a new project and then when we compile it which we haven't yet we just press control shift and B it will build you can now see we got this dll file so this is what a class library is that it is a dll just a code that now we can rest in other applications so now we've got the word core which I don't like being that way around let's move that up oh okay I guess that's staying at the moment short order alpha felony we shall look at way organize that so here's the core project now inside of the WPF we should be able to access this public class one which is in core but first we have to reference this project so just because it's in the solution it doesn't mean that this other project can access this project we need to know about each other or in this case the word application needs to know about the core so in the word application you've got references here expanding you can see what we're referencing that's how we're finding things right click on there and add reference or you can right-click on the project itself and then do add which I thought you put there oh you had reference so you can do it one or two ways go to projects and you can see it's found all pasetta would call check this box and click OK and now we've got their spur Seto would call reference here so now in our code just go to say the application let's just go to base page somewhere we've got some function we can just jump inside off and then here you can see which should be able to now do processo dot words core which it sees and there's your class one so now all you need to do to access like you know class one or whatever is in that library is to make sure you either specify the namespace or you just add the using namespace to the top of your class like that so that's all we're doing is we're we're separating the code out into two projects and the difference here is as well this project the word you can see references the window shall the WPF stuff the presentation we've got the system files we've got windows base all these references mean that this is now a WPF application so we couldn't then reference code inside of here in our iOS application welcome to make it because iOS has no idea what in WPF is or what you know some of these things are whereas if you look at our core library project now the reference ism here a seizure of itself and the Cornett framework stuff which is all accessible in iOS and Android other things so this can be shared this is the benefit of now having a class library not linked to WPF is that we can now share this code between multiple different versions of our software so let's delete this class and let's start dragging and dropping code over so animation has WPF stuff attached property of WPF controls the BPS data model now a data model is simply specifying what page were on so that's useful throughout the entire application not just WPF so we drag data model into facetted awkward it makes a copy we can then delete this original expressions again this is expression helpers I thought that I need to uninstall to stop that expanding this expression helpers is a gap universal viewer so we want to close that down to close all them down a second we want to drag us expressions into the core project and delete it from here the font to use the middle BPF application they stay so our images so a pages security is universal again it's just helping with secure string so drag that into the core delete it from WPF styles or WPF specific value convert as a WPF specific view models are definitely not so drag all the view models into core delete them from there the window is a WPF specific one in fact there's one thing that we need to keep it in as I mentioned a good few videos back we made one view model that was technically [Music] WPF specific as window hew model because we include in the constructor the WPF window so this has to stay in the WPF project and that's good because this is only doing things for a WPF wouldn't know anyway so this is a you know this is fine stained there one thing we need to move out is the this current page so we'll move that out afterwards let's finish what we're doing so the window is the DPF and then all this is WPF so now all's we've done is moved some of the code that should be shared between other projects into a core project so let's just do ctrl shift would be to build and let's see what we've broke so two things have failed which will be both projects well let's have a look at the others so partial declaration of chart page is not be specified it's just an error table let's unload the word project first so we don't get mixed up between two different project errors so here we go so name space corner radius can't be found window view model we need to delete with coffee ballot back already build again we go much less so implement property changed isn't there or you remember this come from Fadi Weaver that we installed in word so let's go ahead and add that to this project so in the core project right-click references manage NuGet packages and we did this again in the word application when we added Fani Weaver so do Fadi property property change dot Fadi Weaver let's install that and that will add the Fadi Weaver into this project as well we know we'll need the other thing which is mutant soft Jason for serialization and things so let's just go ahead and install that now I know for a fact we'll need that and now we can see we've got implement property change back let's ctrl shift and B to build again fix a minor arrow where there's a really the area this is my again editor code you won't see this error but I will because I've got this on it's going to be named run command to run command a sink with control our our build again now in the name application doesn't exist so this is the problem I was telling you about with now all let's move to the register page well now because we're in a call library because view models want to be shared throughout other applications we now can't access this WPF window because this is now going to be run on multiple platforms so this is no longer any good let's just comment that out we'll fix that afterwards and that's it that's now building apparently so let's run we can't start the up oh yeah now we need to unload the word project and see of that still builds so right click on the word click reload project control shift B and now cannot find chat less design model instance really catalyst design model is because we move that into here which is actually fine I think what's happened is that is now a different well the other thing let's fix this first as well now we've moved all these classes into core we're going to go through every file in here and in fact we should be able to search by find and replace by project so make sure we're in this core project cover you know some code open that's from this project and also just to be sure right click on the core and set a starter project to make sure it's bold and then just find somewhere with namespace for setup word press control shift + H to do find and replace all it's already put in what we highlighted and we're going to change every instance of the namespace for setup word to Fassett o word core and we want to look in and hopefully this has got current project yeah current project so we're going to do basically a fine and replace everything in this project core when I basically change all of the namespaces from pasetta word to FS soo cool because that's where these all are contained within now click replace all yes and we've replaced 12 so 1 2 3 4 5 6 7 8 9 10 11 12 code files that's right so now we'll have broken a few more things because now we've moved these view models off into a new namespace that in WPF now where we've tried to wrestle them as you'll see we can't find like this login view model so controlled oft and using Fassett Oh dot word corn how to find them so you'll have a few of those to be honest for how small this project is be easier to just click through the files let's just take a look at every file that seems fine this wants to be renamed to async so I'm just going to rename this so slide and fade out to left and it's returning the tasks so when we named it to async same there again these areas you won't guess they keep mentioning this is just my styling convention that I'm going to start sticking to for future videos so every task will return a function ending with the word async so it's really obvious storyboard that seems all fine so that's got no issues attached properties start at the top work down this is again I'm forcing in fact I'll let me change this I don't want to force this so let me just do it prefer method like constructors for a property so I don't want to do this for any of those at the moment I don't want to force that style you don't have to understand this fit this is again basically because I expect functions to have curly braces in C sharp 7 you can do this instead like a shorthand way of making a function but I was originally forcing them to be you know using curly brackets but the certain cases like this where you know I think it's fine so close and reopen and that should stop complaining at me for doing that now I'm still going to complain use what four body methods I've completely told it to ignore that okay a lot I'm going to ignore that because that's not an actual visual should be aware that should go away I think it's just taking his time to probably need to compile maybe to get it because you can't compile the project at the moment it doesn't seem to want to let go of that so they aren't real hours so that's fine a touch property is fine that's all fine this is where it will get fun chat less control so now I need to make sure and this is why we're doing this now to make sure we're ahead of the game this chat list design model is now in core down here chalice design model so we're sailing Sun local copy and paste US local change this to cool change the namespace to the core namespace let's change where we find in this prompt and that's cool and that'll fix that error when it's compiled f7 to check the code behind that's all fine and that's the majority of what we'll be fixing is just changing the name spaces in sam'l chat less control guessing the same thing the view models converters rather are still where they are that seems all fine there's one again the design model is now in cool so change that to core go up and add a core namespace save that code behind other links down it in milk side menu control this definitely will have some things and I think let's make a call namespace to start with and let's look through for watch means search for local co-op so there's nothing in there using that that one's fine code behind it's fine that's all controls done and this is why one of the reasons why I wanted to separate off into you know multiple projects now because otherwise the further you go the more refactoring you have to do base page base view model control dot and then enter to find the new namespace scroll through use expression body for access as that's what I do want to do this again that you won't get this area this is another style that I want to do control dot and you'll see the fix that's that we can do this getter much easier like that you can instead of having to use curly brackets you can do a nice shortened version like that remove this get rid of this again so this is all me just cleaning up my style that I've now changed a little bit of base page loaded and because this is asynchronous because real waiting in there it's complaining that we don't really want to end that in async so let's remove the async there and we just animate and we don't need to do anything we're going to wait that we just ignore it so fat let's just do a tough stop run and let's run the task independently of the function so that's doing exactly the same thing but because of my naming convention of everyday synchronous here then you want to name this asynchronous it's not really asynchronous this is when the base page loads it's synchronous I was just using a little thing that you shouldn't really do very often and it is to put a sink with void because that means that nothing can actually await this function so even though you can await inside of it the caller could never wait for that to finish so it's sort of bad practice in a way so this is a better way of doing it anyway here and my naming conventions are sort of forced to me to do that now animate in again you can see animating is asynchronous so let's just rename that to animate na think and again that's made this obvious that if we had missed the weight it's got the word async after it so it's really obvious remove this and this is good because now I'm cleaning up all of my code style changes at the same time as doing this move by just going through all of these files and because there's not that many it's fine animate out name to animate how they think that's that filed on chat page has got nothing on it or no one so we find there f7 it's got a view model that's fine as well at different base class login view my ah sorry it has got it we've got a local login view model here that's called login view model nearly missed that one so do the core there I should now not complaining probably just needs compiling now for that double-check that yeah that's fine save that login page again got local that needs to change the call for the view model copy and paste the namespace - cool cool and then let's just have a quick search for local in the rest of the file if I spelled it right so I got local there is busy property that's a value attached property so that's fine where it is and that's it so that files done f7 to make sure the code-behind okay which it isn't control dots find the new namespace and now it's fine register page will be exactly the same because we copy and pasted so change that to call copy and paste up to call and what I think I'll do so you guys don't have to do all this cleanup I'll do all this cleanup and always moving and then our Porsche all of that code into github so that you could start the video from say the cleanup stage where all's I've done is move things around and clean things up to save you having to do this this work which is kind of sort of mundane if you will so I'll do that in a moment when we finish the cleanup that's the register page done Stiles I'm pretty sure they've got no issues we don't rely on anything in styles that aren't in the styles in fact I'm not gonna bother checking I'm sure that okay a quick glance at Windows is you got nothing in that can actually go to make sure the app doesn't reference that which it does get rid of that there's nothing in it and styles go on value converters seems okay they go back a minute application page is now in call at the view model at their namespace rather that's now fine base value converter this is going to complain because it's a static and again I have now changed my naming convention if it's a static member we expect it to just be uppercase to start with so let's just change that to converter and the rest that's fine boolean to visibility converter spine string RGB to brush on your spine yep that's the value converters done that's one view model need the namespace fare control dock to enter new namespace these are currently complaining because again we can shorthand these brackets into this new style which is just the equals greater than and then the function without the return so to do manually on say this one instead of gap being these curly brackets you just simply remove equals greater than remove the return word and then remove the closed bracket and now because we've done the getter and this is also only a getter you can actually go and remove that as well and change us to that and that's a complete shorthand version so again here the gutter you just returned everything because it's only got a getter not a setter equals grade to them and then remove the two curly brackets that's clean manner and this again because you've got a gator in a setter with curly brackets there's no need this is going to clean that up for us control doth enter and remove the comment above move that to there and again you won't get these errors if you wonder why yours and show this it's just because of my styling editor config file but again look how much nicer that looks now so look how easy that is to read compared to an unnecessarily easy to read book shorter so that was what it was and now it's it's that so again this is why I've made this editor style to try and force me to write again cleaner shorter code and all you have to remember when you see something like this is if it's not got parentheses at the end like this which will actually work it will turn it into an actual function or a method if it's not got that and it's got your equals great them then it's going to be a property if you put whoops have you put the parentheses there then it's going to be a method so that's how you tell the difference now between you know a property that's obvious like this because it's going to get on a setter to a property that's not exactly directly obvious yeah they just look a little bit to make sure there's no parentheses there so that this is the same again as you've just seen when you undo the changes it's just a getter so a property where the gatah it's just a pleasure doing it again same for this one I'll speed to these now you know what I'm doing just cleaning up the getters and setters commands are all fine constructors fine private helpers fine that's the window view model done nearly there we've got the window resize er which I'm sure is going to be fine I'm going to bother check-in all of that this can be inlined I'll just fix that one thing again that's something you won't see that's a invest in c-sharp 7 again when you have to when you've got something that want an out so this function wants to set this value for us you pass it as an out so what you usually do you create the variable then you pass it as an out well now in c-sharp 7 you can actually put out and then the type and then the name of the variable all in one line like that so now even though I'm created a variable above it just by passing it in like this it's actually created the variable here so this is like defining the variable and then it's passed it as an out at the same time so below it we've now actually got our mouse position as a variable again just a quicker way of well a shorter way of doing the same thing passing out variables directly by creating them at the same time I'll leave that file now that'll be all done I'm sure of it I've got config you don't need to look at Weaver we don't need to look at past you don't look at so we got the app in the main window left the app is fine f7 for the code beyond there's nothing in that's fine main window last but not least scroll to the top I'm sure there's gonna be some course dropping instead of copy and paste the namespace core and then add dot call at the end and let's do a search for local column so we've got the main window which is in the word application which is local that's fine we've got application page valid converter that's also and that's fine I've got the user control that's fine so actually there's nothing in there that's not in the WPF project so that's all ok so with that cleanup fingers crossed control shift and B should now build this oh what a feeling will still be an error somewhere chat let's design mode that's going to complain you know sometimes this happens as well so even though it core is there anything when you do things with WPF you move stuff around sometimes you need to just unload the WPF project make sure everything else builds which it has and then reload this project and build again and sometimes it just gets stuck in thinking things don't exist like it seems to be here so when ice we're really missing something obvious here so oh I don't like this the core namespace we've specified wrong each time we manually typed in you just click it in the namespace press ctrl + space and then your seats found it now press ENTER and you can see the tally that's going to add this assembly because it's in a different assembly and then it's started building so let's just undo that now let's just do a find replace all so let's select in this namespace control shift H find all instances of that what we just selected paste it in there and we need to change it to whatever it was so let's just go forward to there copy that and add it for there so well basically I find all instances of the word call XML and change it to the new style with the assembly at end and that's current project now to do entire solution replace all yes 6 found that's fix the namespace so now you should finally build there we go let's press f5 and see if anything else works right-click on word and make it the start of project again f5 and there we go we have the application we've got no page here so let's make sure the app view model which is I keep going to app view model I want to make one call that view model we've got the window view model I'm hoping the current page is set to Odia so the current page is now not working because we've got the login page and it's not loading the login page so we've caused some kind of break so let's take a look at the application page value converter put a break in here run the code and I'll see what's doing wrong so we're finding that or same page will returning page and apparently that's loading it so something there is now not loading the page so let's go to did you do a main window the frame so that's finding it you're setting it to a page background transparent so this should show in here if we split this down a bit hide that off again and let's just change this content for the moment to the bad idea that's there just override it like us but find that is the main frame pages like and pages there a stage I know what the issue is so see this thing I said was better to do this way that's wrong what we've done is we've loaded the page and because you need to load the page so there's animate in starts messing with you I slide them from the right which goes in and it takes a page which is a UI item and it starts messing with the page the visibility this is actually going to throw an error this is going to crash here because what we're trying to do it's a subtle thing what I've seen it enough that I can spot it now if we go back to the base page back to the page loaded it comes in it loads and then we animate in right now this call from loaded has come from the actual the UI itself so we're on the UI thread there's multiple threads in an application and the UI thread there's only ever one it's a single thread there's only one thread in the entire system that updates the screen and that's called the UI thread we're on it when we get into here when you're doing task wrong what you're actually doing is then coming off the UI thread and then you're running this function now in just a standard thread that isn't on the UI and there's a rule when you come to edit UI stuff so when you're editing any UI element like a button or a page or anything to do with UI you have to be on the UI thread so there's two solutions to this the first is we just change this back to a sink which we're going to do and we'll fix the name was it call async for now the second if you were somewhere else in code and you run this animate and then you were you boil down to one thing to slide in and you're all the way into this code right here when we're doing UI stuff you could then make a helper function that this stage says right make sure I'm on the UI thread and if not put me on the UI thread then do this code and then come back that's more complicated and I'll cover that in a separate video let's also prove that I'm right here so I'm just telling you I am turn on all exceptions so control Alton the letter E and click here that should always be on this is why you'd get this issue and go what's going on if nothing happens nothing crashes and something doesn't work press ctrl alt Ernie and make sure you've got this checkbox here on common language runtime I expect this will crash but I'm going to put breakpoints after it and we should see that we'll hit here anyway now let's press f5 and run the application again and let's see if I was right so we come to the application to get the page we know that works oh we're actually failing is shorter than that but same issue we're trying to access the page here and the page is UI and we're not on the UI thread as we mentioned so the calling that I cannot access this object because of different thread owns it and that's because when you step back which you can't go any further back than this on here we might be able to see it in debug windows for the Reds tasks threads those threads here we are above so you can see the main thread here is the the it's called main four this is the UI thread it's a managed ID of one so at this point we were on the UI thread here then when you don't a stop run and you come into the animate function or we just jump into this thread you can see now this is just a worker thread this is and there's the garbage collector from windows cleanup but the point is this is on a different thread you can see a thread ID 3 so the reason it fails is because we need to be on this thread the main thread to update the UI so I went a little bit deep there to explain that and that'll have gone over your head in some way but at least to give you a general idea of what the issue was and why and it's because we need to make sure we're changing UI that were on the UI thread and again using view models will actually prevent a lot of that from happening in the first place as you'll see so let's just go and fix this now so for now change this back to async and then we're going to wait this and the reason this works is due to a little bit of trickery and doing an async with a Boyd it doesn't really spin off a new thread so it stays on the thread you're on when you're not you know the call of threat called in and that's awaiting this as opposed a task starting on so because the caller that won't await is anyway calls in we don't break off to a new thread let's just rename this to async as well just so we know it's asynchronous and let's run that again and then we should be back to effectively working up so there we go everything back to where we were we're now also cleaned up so all's we've really done there has created a new project to class library we've moved all the stuff over into this library that is going to be shared so basically anything in here that can be moved we will move because these are all specific to WPF like the page animation is only for animating a page in WPF potentially we could move that to core if we wanted to use that anywhere else but right now that's only used in page animations and a page is WPF so everything in here every class in the WPF application now in the project is all specific to WPF anything else we do is now in this call so that when we come to make other projects we can use this shared library the one thing I said we did need to do we need to move this current page to the core library because the current page is obviously throughout the entire application not just in WPF so in the view model let's make something that I've keep calling and have a major the application view model and this is so going to be the view model for the state of the whole application so make that probably your base view model the application state as a view model something like that let's take this out of the window view model which is now completely anata li related to just the window so just style the window size is the window and what have you pasted listen for the application view model and now we got the current page there ctrl shift + B and just find out what's broken where how its building that shouldn't build I win OS building because the main window is a moment doesn't realize it's failed so jump into the main window right now we're buying into the current page both to view press f7 the window is bound to window you model let's get rid of this there so this is no good because the data contacts in here is the window view model we want an application view model now in order to get to the current page so although this now won't work I'm going to commit this as the cleaned-up code because the next step is to again these another reason why you need it the application view model you want one throughout the application so this wants to bind to just you know the single instance of that view model but how does it get the view model from here so what we're going to use is and inject which is like a dependency injection and it's going to solve all these problems for is it's going to have a universal way to access a view model and then be able to bind to that view model so in fact let's fix this at least so it's a work in project when we commit what we'll do is in the main window we'll just make the public application view model a cool application view model and then you use the shorthand and it's a new application view model so we just make a single instance of it there this is a temporary thing so I'm not going to buy the comment in it but now we can at least bind to this so in the binding you want it to now be the path the element named Rolla wants to be this window so let's check if we've got a name on the window yeah yeah name app window so we want to buy into the app window which if you go to the code-behind is this window so we'll be able to then bind to application view model dot current window and sorry document page so element name app window and the binding path is application view model dot current page and I think that should get us back to working so let's just see if that works there we go so that's now working again just get rid of this threads window close it so I'm going to commit this code this was sort of the cleanup phase if you will we've moved everything off into the shared library we've separated the current page to the app view model and now we want to finally get back to doing this login page well now the login view model rather that we have to comment out to get working we want to now get hold off and you'll see this current page is now in an app view model and again you'll see the temporary fix we've just done has put the app view model back into the WPF application which this file is in the core application has no access to that so we can no longer do this at this stage anyway we can't get access to the view model to change the page so let me just quickly commit this to get up and then we'll come back so that's all push to github now let's clean up and move to call class library as the comment so now we can move on to fixing this register a thing so in order to now access you want to be able to access sort of everything from everywhere in your application that's usually what happens you you somewhere in code and you're like how can I now access this and the issue is having that control of where where all that information stored and how it works so it's easier to show than explain so let's just go ahead and install what's called an inject and while add that to both projects so right-click references manage nougat packages and then in browse type n inject and the top one install that accept the license it's done right click on word as well manage NuGet packages and inject install that also got an update apparently check out what once a dating party can be updated that's fine it's up data to override the file so we've now got anyone's update in here as well on second just keeping everything up to date so same here buddy update don't override buddy failed to uninstalled please restart okay let's just quickly restart visual studio and that's now uninstalling that double-click that doesn't work that's it so don't bother installing this double-click maximize extension it's useless restart visual studio open up the project and now we've got an inject installed all that's done is in your references we've now let us and inject that's all that's done added the reference so we want to now make new sabar and let's just start by basically doing that so in core right click and add a new folder and pause IOC and that stands for inversion of control and that's because we're now passing off control of finding services in our application off to n inject create a new class in there we'll call it just call it ioc container it's a public class be a public static class because we have one instance through the whole application and the ioc container for our application and in there we want a public static and its internal its eye kernel and then control dot to find the namespace using an inject call this kernel expose that the Gaston with a private sector and it's a new standard kernel comment that the kernel for our ioc container and the kernel is basically where you get and bind all of your information in the hole of an inject so again you'll see this happening we want to have a public static void configure let's say this is the thing that needs to be run on fellas call it setup that's what we're doing we're setting it off since of the IOC container fines for information required and is ready for use must be called as soon as your application starts up to ensure all services can be found so we're going to have our app calling this setup so we've got the container ready so in the set up we don't need to do this because we've already done it ecstatic so that will happen that's just going to get created anyway and but as well as creating a new kernel well that's really Ethel's we need to do - to set up there you know the whole kernel we also now want to do some binding so we want to bind all these view models this we won't see a single instance of and right now the only thing we want one of is the application view model we can have a single one and a login view model but again we don't need it right now but we do need to access this application view model to change the current page of the application so we have to change this throughout the application so we want one instance of this because we only want the single application view model so let's bind or required view models call it by new models control dot and enter to make the function fine or single term view models so we call setup it calls this and then here we want to use the kernel and we'll call bind the type is application view model and you can do one or two things you can do bind dot for self dot in singleton scope which basically is saying create a single instance of this class whenever you call you know whenever you try to get this it's always a single instance but what I prefer to do just in case you want to change something about that you want the you know instant 88 create something I'll set something up the same is doing to self but in singleton scope is to do dr. constant and then in here just make a new application view model and then if you ever want to set up or change that view model you know set up some data as default like the current page you can now set it up here and change the current page to say register you know on startup so gives you a bit more control doing it this way that's going to create a new application view model find to a single instance of application view model so by doing this kernel dot bind now anywhere in the application that can access this kernel can do kernel get and try and get this back so that's what we're going to do there like we think we also want to window view model now we can do main window yeah that'll do for now so in the app now because on startup we need to initialize this container the first thing that WPS does when it starts off is it goes into the app and then inside the app it does a startup function and then the startup by default it's gonna then read this startup URI and then spin up the window while of our window main window here expect and it will do to say get out a window view model or to get something like this for example you want to change this to now get the view model from the kernel we need to make sure that we've initialized this container we've called the setup function immediately so before anything runs so we first want to change the behavior of the application starting up we want to control ourselves so let's delete this main window start up main window let's go to the code-behind now if we ran which I think it should build then we've broken anything yet yeah so we've run now you'll see the bar will go orange at the bottom but we get nothing we're running an application but we've never started up anything we never opened a window there's nothing there because we removed the start of URI so now if we override the on start off we do all what the base needs to do custom start up so we load our IOC immediately before anything else let the base application do what it needs and then after that we want to configure our ILC so we'll call ioc container which is a static class in our core which we can either using ioc containers not capitalized see for some reason typo ioc container dots a top so setup dependency injection right away and again as you start typing this so application you want to type ioc container for everything let's just make a quick short Angela so public static class IOC and we'll start mimicking some function so shorthand named for the IOC and plot now let's forget making a short on class let's just rename a class to IOC and then a light bulb rename the file so when I was called the IOC spit shorter so IOC dot set up so we set up the IOC which I'll just go into this function call this function and simply bind an application view model so we get a new application view model that we can access everywhere and after we've done that we just need to now show the original window so show the main window which is what we were doing before when we have this start up URI that's currently that main window equals new main window current dark main window dot shell and that's all the start of URI does anyway so now if we run this code we should see we hit here the application runs we call that we set up the IOC create a new window and then it's shown so we're back to where we started but now we've taken control of the start up away from the start of URI and we've done it ourselves so that we can inject our we can set up our IOC straightaway what that now means is anywhere in our application that's referencing core which should be everywhere because that's the point of a core libraries is the fundamental you know part of your code that everything has a reference we can now go to main window and instead of this be an application view model you don't even need that because we've got it in the view model I would vote in the ioc container so now let's go to our suppose from these windows down let's go to our login view model and angleman let's change this binding again so the binding which was now binding to the element of this window to get the view model now we want to bind to you know a specific view model of a specific name or of a type rather so we want to find we need to do a converter to take in say the name and then pull out a specific type from the ioc container so i'll do this a simple way and then we'll improve on this in another video because i don't want this to take too long so for now let's just name it application view model and we'll just literally check for that string for now the converter we want to call it IOC I also you convert a simple of that so just going to have a value converter copy and paste this one call us IOC converter trip up to rename the file to IOC converter which it's done there we go the base value converter of IOC converter converts a string name to a service call from the IOC container and converts which the value on a string case change it to up yeah I'll just do this for now and we're going to call it application view model or in this case actually application view model name of so a list of where we name it that'll rename and that is not a very nice way of doing it yes because that relies on us then having to add this everywhere as opposed just finding by name so we'll improve on this but for now we'll basically take in this string name and pass it application view model and we'll find it here because this basically takes this hard-coded class and name off turned it into a string so we're just instead of name of you could do and this but the issue there is if we then go and rename our application view model this won't get renamed if we do name of and we rename this obviously you can see in there it gets the new value so this just checks for the application view model if it finds it will return and this is where the cool thing comes in ioc DAST and then we haven't got a helper function yet it's basically Colonel GATT and get services I thought it was a guest application view model then we need a yeah using that inject so that's all you now need to do to get the application view model that we bound in here so this exact instance here from anywhere in the application you can now do is you don't get so let's turn this into a helper function just IOC GATT controlled asked f12 to go to the function it made for us let's clean up this class a little bit public trough peace we on use namespaces this will be piped e gets a service from the IOC of the specified type try to get and we just simply return the kernel dot yet T and that's it so we just a shorthand way of calling that this is let's call this I know it's not strictly a constructor but we'll call it construction so it's pretty obvious that it's ER sort of setup in fact the bindings also part of the construction that's like the set of code and then move this below so we're now going to get function we can now call get here so what should happen is this should build I think it's just complaining because we haven't yeah there we go so they should now use the local IOC converter we just made it'll pass in the string application view model and we should then pull it out of the injection to now find the application view model so we press f5 with a breakpoint in there should start up yet nothing happens so oh and not we've found out as a point this binding this is the path that's not the path that we want we just literally want to convert it from a value converts a parameter I don't really can just pass it can't do that I'll see we can do a blank binding again we'll probably improve this I'll think this through a bit more afterwards and maybe come up with a nice or you're doing this let's just try a converter with a convert the parameter application and view model so it should really defined you will be bound to whatever this Windows bound to which is the window view model for now so technically is a work but will improve this so we can do something a bit smarter here but this are now buying the converter with a converted parameter which i think is what we were looking at anyway now we're looking at parameter so what now look at the parameter so let's see if this works so there we go we get the parameter which is a string value of application view model it matches the name application view model so we return the application view model from the IOC and yeah it's actually returned the application view model and that was because we bound it to that we need to convert it further so we've now got the view model but that's not really what we wanted we wanted these and we wanted to convert convert the view model in fact in the view models here let's add a class and this is called a view model the way we do this called a view model locator usually and again it's it's kind of not ideal but for now again that's all getters going this wants to be how do we do the static value convert as a car number I think instance thing we did they to touch property we did like a instance of a static with a class that wasn't so we will want fact I think we can just do static view model locator where static application new model a patient view model which is IOC get application view model and now their application exception are typed application view model such as check this works and I think will use static view model located our application view model so well the application view model is what we want the sauce will be static view model locator I think and then we can change the converter back to what it was which was the page converter thing station view model stop calling page and a converter is application page converter so see if that works gone to the clash you got to an instance of yourself okay your mana locator Abbott class with public static model locator instance see if that works okay doesn't exist and I know what's happened the locate has got the name space armed Thank You Visual Studio remove laughs build finally there we go still complaining bye there we go so what we have to do is in order to reference it as a source to bind to similar to an attack property we made the view model locator a class and then we have to create a property because you can only do a static to a property not a class so we just made basically a static instance of ourselves so a singleton instance of this view model locator so locates view models from the IOC for use binding in sam'l files so we only need desk due to being able to bind in sam'l to be able to do this otherwise you can just type you know IFC gas and get what you need so this is used in binding to find one so this is a regional public property properties soon with an instance of the locator and then this is the actual application view model so we can call into that and then all we did was similar to how we do attach properties the source of the binding we first tell it to use the infant's of this view model locator so it's going to use this class as the source of binding and then we're going to get the application view model which is here and then dot current page so it's going to be the application view model we go into it and then the current page so all that now is just them pulling out the current page from effectively boils all the way down to this instance we made right here so everything that we accessing the application view model from is from this single instance here so that gets the current page now from there as the source that way then we use the original converter that we had as well so that's now the new binding which now uses the dependency injection to get the view model and bind to that page now why we did that is because now if we now want to change the page of the whole application it's bound to the current page it's bound to this view model that's here in the core that's accessible everywhere so now in order to go back all the way back to where we started with our register page which then boils down to our login view model here and we get to here finally right go to the register page how do we do it now well it can be simpler IOC get application view model current page equals register and that's it so anywhere in the application now we can call the IOC we can get this instance that we've used everywhere in the application we've bound it in the sam'l here we've now used it in the log in view here we've got that instance doing this and we just change the current page so we press f5 we should now have a fully working binding to end in Jack that will look like here it's now loaded the register page so that might have seemed like a lot of work and I know we've done a lot of clean up as well everywhere else and we've covered quite a lot there I'm hoping you didn't just get lost in me sort of ranting on a little bit and cleaning things up but you can see we've we've moved up ninh into a core library which is now something that's got no reference WPF so we then cleaned up all the code there made it work again we then added an inject as nuga packages to both libraries we made this ioc class which really does nothing more than create a new kernel here which is basically somewhere where you store all the bindings we set it up in the app sam'l code behind to make sure it's set up which then binds right now all we need is application view model to a single instance then we update the main window to use that instance and then finally we updated the login view model which is in a different place in code to now change effectively the current page of the application so now we could change the current page anywhere at all in our entire application by just accessing the ioc and that's called dependency injection and at the start I left a window open with an injecting so if you go to github.com and inject and inject wiki you'll get this nice page which you can then do a bit further reason if you want to understand but at least now you've got a working project and you can see it in use and then you can go ahead and read through this so why use any inject and then getting started and then dependency injection by hand if you would to use it and then using that inject and you just read through all this and you'll get some understanding of of what's happening but until you use it I think this would be quite overwhelming just reading about something you haven't used as a bit daunting so there's the use of it now we can now in fact register async is yeah this will become asynchronous because we're going to fix this to a way to page change and animate improperly but for now this is now the page done so we've covered they're really splitting your project into multiple projects basically and then we've started our dependency injection which is now going to rapidly expand in the application so one of the other questions was in the main window how do we then change this you know side menu self click this button here or I've done something else somewhere off in the code and now I want to change the side menu bubbling back up and then being able to change that is now going to be really easy because walls will do is up here at this end will bind this this content here to a view model of specific content types and then anywhere in code you just use the IOC to get that view model and change you know change it that way so now you're going to start working with the ioc a lot so this is this is a pretty advanced topic as dependency injection so hopefully this is this is really just the introduction to the dependency injection the very early stages of doing dependency injection but at least now we've got in there we can start using it I can start explaining it more as we go and you've seen that the correct way of how to now change a page you know anywhere in the application and we can start building on this now we've now got an application where we've got a login page that we can click to to go to a register page and the same way around with another register page to go back to the login page we can out these buttons to do the same thing we can change the title of we bind the title to that as we can do whatever we like now so next video will either do a bit more clean up on the dependency injection will either do the animation on the register page login page or we'll do some chat bubbles we'll see where we go but hopefully this has been another useful video and let me know what you think [Music]
Info
Channel: AngelSix
Views: 47,330
Rating: undefined out of 5
Keywords: wpf, dependency injection, ninject, inversion of control, view models, mvvm, multiple projects, class library, dll, large project, tutorial, example
Id: w5kAUCFDRy4
Channel Id: undefined
Length: 96min 7sec (5767 seconds)
Published: Thu Apr 06 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.