Dependency Injection Integration - WPF MVVM NAVIGATION TUTORIAL #8

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
we've gone over a lot of key navigation concepts but one thing i want to cover and one thing i've kept on mentioning is how to integrate this with microsoft built-in dependency injection so dependency injection pretty common for net apps so i feel like i should show off how to do this rather than just throwing all of these concepts at you so that you can actually integrate this with your app and doing this navigation might not be as straightforward as you might think when integrating with dependency injection so we're going to go over how to do that and we're also just going to be setting up dependency injection in general so kind of a soft introduction to dependency injection as well so here in our app the way we set this up is we instantiate all of our stuff right here so our account store navigation store and modal navigation store which we just covered and then we simply use those in our startup so ideally rather than manually instantiating everything right here i'd want to register these in dependency injection and then resolve what i need so i'd want to resolve my main view model maybe even just resolve my main window that would include the main v model and also in my startup i'd want to resolve some kind of navigation service just to do the initial navigation for the application and set the initial page so let's begin by installing the nuget packages for dependency injection so that's actually right on this browse page so we have microsoft extensions dependency injection and i'm using dot net core 3.1 so i'm going to use 3.1.12 as my version not using.net 5 yet i probably could be but i'm just not at the moment and that is actually everything we will need so let's start off by getting a dependency injection container set up and we're going to do that in the app constructor by using an i service collection i'll call this services and we're going to instantiate a service collection and let's import everything we need so the microsoft extensions dependency injection and now we have our service collection that we can register all of our services with so the first service we want to register is our account store and our navigation store and our modal navigation store so we want to register those as singletons because they store our application state and that's the same logic we kind of have right now by just instantiating them once in the beginning of our application except now we're going to register them as singletons instead of manually instantiating them so we want the account store the navigation store and the modal navigation store and let's remove the fields that we have for those and remove the manual instantiations let's also register the main v model and that's going to be a singleton as well we're only going to have one main view model for our application and the main view model does depend on a navigation store and a modal navigation store but we already have those registered so we are going to be able to resolve this successfully and while i'm here i'm also going to register the main window we'll just register this as a singleton and we're going to have to register this using a factory function right here so we'll instantiate a new main window and the reason we want this as a factory function is because we need to set the data context and this factory function to create the main window takes in our i service provider so we can use that service provider to resolve our main view model and then we'll set that as the data context and all of our bindings on the main window will work and now we are ready to build the service provider so that we can start resolving our services so where do we want to resolve these services well we want to do that in this startup method so that being said we're going to put our service provider into a field so that field will be a service provider and let's generate that as read only since we do all this in the constructor and it can just be an i service provider and now that we have this field we can use that down here in our startup so our main window we will resolve that from the service provider get the required service and that is the main window so that takes care of the easy part but what about our navigation services and what about our view models we're gonna have to register those in dependency injection as well because we can't just create those here because we don't have access to our navigation store and our modal navigation store in our account store because those are all registered in dependency injection as well so the quickest way to get this working is just by registering the home navigation service in dependency injection and then resolving it here so we would do something like service provider and then get the required service and we want an eye navigation service and since we've resolved this as an eye navigation service this means we can only have one eye navigation service registered even though we have multiple different eye navigation services for our application and that means the i navigation service that we register is going to be the navigation service that is used for the initial applications navigation so we'll call this the initial navigation service and this navigation service is just going to set the initial page that we start up on so we're going to register that and i believe we can just register this as a singleton so the i navigation service and we're going to register this with a factory function that takes in our service provider and in fact we can just use our existing create home navigation service function so let's go to that and right now this isn't going to work for us because this create home navigation service function requires the navigation story we don't have that in this context but we can pass in the service provider to this function so this will now take an i service provider and now we can use the service provider to resolve the navigation story that we need just like that and that fixes our issue but now this create home navigation service also calls the create login navigation service so if we go to that this requires some dependencies from our service provider as well so no big deal we'll just pass in the service provider here as well so add a parameter to that function and now we can get all the services that we need so we need our modal navigation store and we can simply get that from the service provider that has that registered and then update this variable name and then we also need our account store in this function as well for the login v model so we'll simply resolve that from dependency injection as well and update this variable and now this create login navigation service calls the create account navigation service function and that is also going to need the service provider so this is just funneling all the way down as it should because we want to resolve everything from dependency injection so we can get our navigation store here and our account store will resolve that and now inside of create account navigation service we call create home navigation service because the account view model needs that service but this function now takes a service provider it's no big deal we can just pass that in so we have that as a parameter here and now last but not least we have the create navigation bar view model method and that requires some services from dependency injection as well so we're going to get that as a parameter in this function let's just copy it from up here and we need our account store so resolve that and then all of these navigation services need the service provider passed to them and last but not least we have to update this create navigation bar viewmodel method that we use as a func right here and actually open this up and pass in the service provider and we have to do the same thing up here for the create home navigation service as well alrighty so we got dependency injection set up let's run this and make sure everything still works so there we go we're on the home page initially let's go to login that pops up so that's working out well let's actually do the login we get taken to the account page we are logged in our navigation bar updated so everything does seem to be working as expected of course our application isn't the best but it does demonstrate navigation pretty well so we have the dependency injection working but i'm gonna be honest this is all kind of nasty all the nesting we have here with resolving stuff and then instantiating these funks we should probably split this up a little bit so one thing we could do is register our view models in dependency injection up here in our container so let's register some view models up here and we are going to register these as transient so the reason we're doing transient is because we dispose our view models so if we dispose of our viewmodel that means we're not going to be able to use it again and we're going to have to resolve a new instance so if we register these as singleton we're going to get the same instance every single time even though we already disposed of that instance so we want a new one we're going to register as transient so we get that new instance so the first view model we're going to register is the home view model and we're going to register this with a factory function that takes in our service provider and just instantiate a new hmv model right here and that takes an eye navigation service so that is the reason why we're going to have to register these with factory functions because if we just let the framework resolve an eye navigation service then it's going to resolve the one that we have registered here because we can't register multiple eye navigation services so just resolve this one that's not what we want so we are going to have to manually pass in the navigation service that we ultimately want to use for the home view model and in our case that is the login navigation service we have a function to create that create login navigation service and that takes the service provider so now down here where we create the home navigation service instead of just instantiating it here we can resolve it from our service provider there we go the home view model and now let's do the same exact thing for the account view model so we're going to register that as transient instantiate a new account view model and that takes an account store so we can get that from dependency injection as well let's split this up a little bit to new lines so resolve the account store and then we want the home navigation service we have a function to create that and next up we want to register the login v model so we can instantiate that in this factory function and for this takes the same services except now we want to pass in this composite navigation service that closes the modal and takes us to the account page so this is going to be pretty advanced and what i'm going to do for this is move this factory callback function to an actual method so this would be create login view model and i definitely like to do this whenever the registration factory gets way too big so now we have this method down here and we're going to return a new login v model we can move our composite navigation service to this function we also need the modal navigation storage so we can paste that up here as well i suppose i should call this service provider for consistency update that and then we'll pass in that composite navigation service to the login view model and now down here for creating the login navigation service we can just resolve this instantiated login view model from the service provider and i believe we no longer need the account store here either so we can remove that and this is much simpler now whoops and for the account navigation service forgot to resolve that from dependency injection rather than instantiating it right here so let's go ahead and do that resolve the account view model i definitely like to register as much as possible in dependency injection so we can also register this closed modal navigation service so we can just register that up here we'll keep it with the other eye navigation service so the close modal navigation service and that does not need a factory function because all of the dependencies for this service are already registered in dependency injection so now instead of instantiating it right here we can simply resolve it and now we don't need the middle navigation store because that was just required for the closed modal navigation service so slowly but surely we are getting simpler and the only reason it's really complex is because the eye navigation service can't really be registered since there are multiple eye navigation services for applications we have to do a lot of manual instantiation with all these factory functions but it is doable and as long as we split it up into all these little functions it's pretty easy to manage i've noticed in my own applications so the last thing i think we could do is register the navigation bar v model independency injection so rather than using this function we can use our service provider to create the navigation bar view model so resolve that and we'll do that everywhere else we use that so i think just for the home navigation service and now we can simply register the navigation bar view model using the create navigation bar view model function so i think that's actually the most i want to do here now keep in mind we could do more so let's consider the layout navigation service and that takes the navigation store a func to create some kind of view model and a func to create a navigation bar view model so the only dependencies that aren't registered in dependency injection for the layout navigation service is the func for whatever view model and the func for a navigation bar v model i feel weird it's saying funk maybe let's just say call back but anyways we could register these function callbacks in dependency injection as we have right here and then we would just be able to resolve the layout navigation service for in this case the home view model rather than having to define a factory function here but i feel like that's a little bit overkill and i feel like i'd rather just have this defined in its own function just in case i want to change whatever navigation service i want to use for the home navigation service so i'm not going to do that but you could if you wanted to i'm just going to leave what we have right now because this is a pretty good solution that we have here so we were able to get everything registered in dependency injection and resolve everything that we needed for our application including the initial navigation which we do on startup and our main window and then all the complexity we have tucked away in these functions that we can use for the more advanced registrations with dependency injection you can also move these functions to their own file you can even move your entire container to its own file as well which i do like to do for my own applications but i'm not going to cover that right now and you can also do some fun stuff with extension methods as well but this is just the basics of getting dependency injections set up with our navigation infrastructure so hopefully you can implement this in your own applications if you have any questions criticisms or concerns about this setup be sure to leave them below in the comment section other than that leave a like or subscribe for more thank you
Info
Channel: SingletonSean
Views: 2,646
Rating: undefined out of 5
Keywords: wpf, programming, visual, studio, xaml, custom, control, generic, system, line, display, timer, template, binding, behavior, c#, how, to, series, tutorial, easy, time, maintain, package, design, part, event, code, framework, view, style, wrap, panel, stack, scroll, viewer, bar, first, width, usercontrol, command, async, handling, func, action, task, void, model, layout, user, password, box, mvvm, validation, notify, error, icon, class, callback, delegate, relay, clean, simple, switching, views, navigation, nav, modal, viewmodel, dependency, injection, inversion
Id: 6vbZQhryBBM
Channel Id: undefined
Length: 14min 28sec (868 seconds)
Published: Sat Jul 03 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.