WPF MVVM Tutorial: Build An App with Data Binding and Commands

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video we are going to use the mvvm design pattern to implement this application this application is a record book it stores the name and email of a user and will be able to add a user as well as filter a user by name now I hope you can watch this video through its entirety so that you can fully understand how to implement the mvvm pattern by the end of this video you'll be able to implement the mvvm pattern for your own WPF projects I'll try as much as possible to be clear and concise so with that being said let's go to visual studio and get to the coding so what I have here in Visual Studio is a WPF project setup and for this project I'll be implementing it following the mvvm design pattern the mvvm design pattern standardizes a way in which to structure an application in this case we are going to structure the application by splitting it into three layers The View layer The View model and the models layer so what I have here in the project are three folders views view model and models I'll be placing code in each folder depending on which layer the code belongs to so what I have here is a simple Record Book application it's going to keep track of a user's information so that's the name and the email of the user all right so let's examine what we have in the views folder so here in the views folder I have two views defined Main and add user view so what we see right now is the main View so here in the main view is a simple list view that's going to display the list of users a button and a text box we're going to use this text box to filter out a user by name now if you notice that the style is slightly different that's because I created styles for these controls and I place them in the app.zamo file so since this application is going to deal with storing users the first step is to create a class that's going to represent a user so to do that I'll simply add a class to the model layer so here in the models folder I'm going to add a new class I'll simply name this class user and I'll set it to a public class the user class is going to have two properties that's the name property a little bit of the type string and nullable string name and email so I'm going to also Define a Constructor for this class all right so there we have it and this is the user class now I'm going to create another class this class is going to help us query users as well as store users I'm going to name this class user manager now because this class is dealing with the data of the application in this case helping us query and save new data I'm going to place this class inside the models folder so right here in the models folder I'll add a new class and this time I'll name this class user manager I'll set this to a public class and this class is going to have a property and this property will be of the type observable collection it will simply hold a collection of user objects so specify in the angle brackets the type is going to hold in this case the user type I'll simply name this database users now in a real world application you might query data from the database in this case you do not want to query data from the database so what I'm going to do is I'll simply hard code some users here so simply set that to a new instance of the collection and right here I'm going to Define some users now for the sake of speed I'll simply paste the users here all right so there we have it so we have a bunch of users defined here and we store them inside this database users property now I'll make this property a static property and in this class I'm going to Define two methods the first method will be the get user method and the second method will be add user so simply say public this method will be a static method and it's going to return a collection of users the name of the method will be get users so what you do simply do it will simply return the database users which we have had coded here all right now I'm also going to create the second method so simply say public it'll also be a static method and this method won't return anything it's only going to add a user so simply set the return type to void it's going to take in a single argument of the type user what this method will do it will simply add this user pasting through this argument and it will add it to the collection so database users then simply add it to the collection all right so there we have it so we have the user class and we also have a user manager which helps us query data of the user type all right now what we're going to do is let's go to the main View now here in the main view we have a list a text box and a button this button will be used to add a new user when this button is clicked we are going to open another view and the view we are going to open is the add user view let's take a look at the ad user View now the ad user view is a simple window with two text boxes this is going to allow us to provide the name and the email when adding the new user now here in the main view when this pattern is clicked we are not going to initiate an event we are simply going to initiate a command or rather we are going to invoke a command in the mvvm pattern we try as much as possible to minimize the use of events so we'll simply invoke a command and the command is going to direct us to the logic that we need to execute so in this case I'm going to create a command class that we are going to be using for this application to do that I'll simply go to the project and here in the project I'm going to add a new folder I'll name this folder commands and within this commands folder I'm going to add a new class I'll name this class the relay command so this class is going to Define how the command is going to point us to the logic that we are going to execute so what I'm going to do is I'll set this class to a public class and this class is going to implement an interface and that interface is called the I command interface so now that I have this command I'm going to implement this interface or simply press alt and enter on the keyboard then I'll select Implement interface all right so this command class has two methods that we can see here the can execute method and the execute method when a command is invoked it's going to execute these two methods starting with the can execute method followed by the execute method now here we can Define some logic that we would like to be executed but that's not the best way of doing it so what we're going to do is we are going to implement this class in such a way that whichever class is going to use this class that's the class that should point us to the method to invoke so in this case what I'm going to do I'm going to create a Constructor and after I do that I'm going to create two properties and this property will be of the type action and this action will take in an object I'll name this action the execute action and I'm also going to create another property this time it'll be a predicate in this predicate we simply take in an object as well and I'll name it can execute predicate now this action and this predicate are simply methods and an action is a method that returns void it simply performs an action but this method should take in an object and here we have a predicate a predicate is a method that returns a Boolean but this should take in an object as an argument why do I create these variables well because we see that the methods that are going to be invoked one returns a Boolean and one returns void but they all take in parameters so what I'm going to do here in the Constructor is whenever a user creates an instance of this class they should specify two methods and when this command class is invoked we are going to execute the chord that will be defined in those two methods so here I'm going to add an action The Constructor and this action will be called the execute method I'm going to add another one and this will be of the type predicate and this will be the can execute method all right so there we have it so once the user passes these two methods and these are simply references to a method we can then save those two methods in these two variables so the execute will simply be equal to this execute method and the can execute will be equal to the can execute method that would be given by the user of this class now these two properties will be set to private so these two properties can only be used within this class now that I have the two methods that the user specifies by storing them in these two variables what I'm going to do is I'm going to now execute these two methods now for me to execute these two methods I need to place them right here in these other methods so for the can execute method I'll simply return whatever the user is going to return so in this case we get the method and we simply invoke that method now the method should take in an object so we are simply going to pass this parameter and this parameter comes from the command so in the UI when we invoke a command we can pass an object so here we'll simply get this parameter and pass it to the method and that's it then for the execute method we simply execute whatever method the user is going to provide so we simply place it here and we need to pass that method an object simply pass it an object all right so that's it for this command class let me just do a quick recap all right so in our view if we invoke a command the command is going to execute these two methods now we do not want to Define any logic Within These two methods so what we do is we allow the user of this class to specify two methods and they have to pass those two methods when creating this class so through the Constructor once they pass these two methods we can then place them within these two methods so when the command is executed we are simply executing the method that the user provided and here we use an action and a predicate why because the method should return void and taking an object we use the predicate because a predicate is a method that should return a Boolean but should also take in an object all right so that's it for the command class now let's go to the main View all right so here we have a main view now for us to display data here in the UI according to the mpvm pattern we need to create a class that stores the data as well as binds some commands to the UI like for this button in this case now to do that we are going to create a class and we are going to call this class the main view model so right here in the view model folder I'm going to add a new class and this class will be called the main View model I'll set this class to a public class now I'm going to Define some properties in this class and these properties are going to bind to the main View so in this case I'm going to Define a collection that's going to store users and that collection is going to bind to this list View and I'm also going to define a command that command is going to bind to this button all right so let's go back to our main view model so here I'll start with the observable collection and this collection will be called users it is going to store the type user now here we see that the class user is not resolved the reason for that is because we defined this in our models fodder here so we need to add this namespace and we can simply do that by adding a using statement simply say record book then models alright so there we have it now the second property I'm going to add to this class is a command property and I'll simply say this will be of the type I command and I simply name this command show window command so this is going to show a pop-up window that we are going to use to add our new command all right so there we have it now these are simply variables they do not have any data Associated to them so I'm going to create a Constructor and within this Constructor I'm going to assign some data to this so here for the users I'll simply say user users is equal to the user manager class so we're going to use the user manager class and we are going to use the get user methods so this method is going to return a collection of users and store them to this property here the command we are now going to assign this command to a new instance so we're simply going to say command is equal to new relay command now remember that when creating a relay command we need to specify two methods and once this command is invoked we are going to execute the logic in those two methods so the first method will be the show window method and the second will be Ken show window all right now at the moment we do not have these methods defined here so what I'll simply do with the help of Visual Studio I'm going to generate these two methods so simply press Alt Enter or generate this method cannot generate this method as well all right now notice we have two method one returns a Boolean so here we are always going to return true this method will be executed first and this is going to determine on whether the command should continue invoking or not so in this case we want to continue invoking the command so we just return true in some cases you might want to implement where you will return false but in this case we always want to return true so we'll leave it to that now here in the show window we are going to add our logic so in this case what I'm going to do is I'll simply create and add user view so simply say add user now remember we have a view here called add user so I'll simply create a new instance so say add user say add user window is equal to a new instance now once I have this user I'm now going to display this user window so simply say show all right so there we have it so we have two properties users and the command when this command is invoked it's going to execute these two methods and all this is defined in the main view model now let's go to the main View now here in the main view we need to bind an instance of the main view model to do that we need to go to the code behind of this main View all right so here in the code behind in the Constructor of this view I'm going to create a new instance of the main view model this class contains the data that we need to bind to the view so simply say main view model is equal to a new instance of the main view model class all right now that I have this instance I now need to bind it to The View now to make the data available in the view I need to set the data context of this View to this instance so simply say this then I'll say data context then I'll set it to this instance so what this does is it sets the default object for data binding to this main view model so here we can now go to The View and here in The View for instance we have the list view here I'll simply say item item Source then I'll simply set a binding and I'll simply bind this to the users collection now the question is where is this data coming from well right here in the code behind we set it to the main view model so the data is actually coming from this object here and here in the view all we need to do is just specify the property that we want to bind these two all right for the bottom or simply set the command to a binding so simply bind this to the show window command show window command all right now remember that these two properties were defined in the main view model right right here users and show window command so once we create that binding we can now bind to those two properties all right so let's go ahead and test the application all right so the application is up and running and here we can see that our list view is showing a bunch of users but here we can't see the name and the email we're going to fix that in a moment now here we have a button and we bound this button to a command and that command simply invokes some logic so in this case if we click this button we should be able to see a pop-up window and there we have it so we have this window showing up here so simply close this and I'll fix this binding here now here in the list view we have a grid view defined and we have two columns here we have the name and email column so we need to specify here to say we want to display the name and to do that we'll simply set the display member binding we'll set that to a binding and we'll simply bind it to the name property we'll do the same for the other column and this time we'll bind it to the email all right so let's go ahead and run the application all right now here we can see the list of users displayed and we can see the name and the email now if we click this button here we invoke the command but if we try to change the name here and add an email address here if we click this nothing is going to happen the reason why is because we haven't yet defined a view model for this view the view model has to bind some data here as well as run some logic so let's go ahead and do that so simply close this close this so if we look at the ad user View we see that we would like to bind to properties name email and also have a command for this button so I'll go to the view model folder and I'm going to add a new class in this case I'm going to name it add user View model all right so there we have it and I'll set this to a public class and I'm going to add two properties the first will be name and the second one will be email now I'm also going to add another property which should be of the type I command and this one will be the add user command all right so there we have it now I'm also going to define a Constructor for this class now we do not have the namespace for this command so simply add that namespace so simply say system Windows input now this command will be set to the relay command so simply say add user command is equal to a new instance of the relay command and we need to specify two methods so in this case the first method will be the add user method and the second one will be the can add user so with the help of Visual Studio I'll generate these two methods or simply say Alt Enter generate I'll do the same for this method now the can add user should always return true and here for the add user we are going to add some logic that's going to add the user to our collection so in this case I simply say user manager then I'll simply call the add user method the add user method we simply add a new instance of a user now the name of the user and the email of the user will be specified according to what we are going to type in the text box now we are going to be binding the text boxes text property to these two properties here so I'll simply get this property and set the name of this user to whatever property we're going to type in there I'll do the same for the email so email is equal to email all right so there we have it so when the button is clicked we simply ask the user manager to add a new user then we specify a new user based on the name and the email so there we have it this is our add user view model so let's go to the add user here in the view we are going to bind these two properties which is the text property so we simply say text property is equal to a binding and we're going to bind this to the name and for this property here simply bind it to the email all right for the button we simply set the command to a binding and we're going to bind it to the add user command all right so we have bound this to the view but this data is not yet available to the view why because we haven't yet set the data context so the view doesn't know where to get the name email and this command to do that we need to go to this views code behind so here in the views called behind in the Constructor I'm going to create a new instance of the add user view model class so simply say add user view model is equal to a new instance of this class once I have an instance of this object I'll set the views data context so say this then data context is equal to this very object all right so there we have it so we can go ahead and run the code all right so here I'll simply add a user and I'm going to add a name Jamie and I say Jamie at one two three then I'll say add and here we can see a user has been added I can continue to add and we still see the user being added if I change this to another name like mic all right so there you have it now at this point I'm going to implement this text box filter property so we should be able to filter the list by name so simply close this and I'll go to the main View all right so for this feature I'm going to use an event handler so what I'm going to do is I'll simply set a a text changed event handler on the text box so here we have the text box and we give it a name filter text box so I'll simply say text changed event then I'll set it to a new event handler all right now let's go to the code behind of this main View all right so here we can see we have an event handler and this event will be raised every time the text in that text box is changed now if we go back to the main View we can see that we named this list View we give it a name and we give it a name user list now we can actually access the items of this list and filter the items so to do that right here in the code behind I'm going to access the user list so simply say user list then I'll get the items and this items property is of the type item collections so this item collection property allows us to apply a filter method so I can simply say filter and the method that we specify here is going to determine on whether a user should be part of the list or not so in this case I'll simply name this method filter method now we do not have this method defined yet so with the help of Visual Studio I'm going to generate this method so I'll simply select this then Alt Enter and or generate the method now notice that this method returns a Boolean so if it returns true it means that object should be part of the filtered list if it returns false it shouldn't be part of that list all right so what we're going to do is we are going to Simply get every user inside the list and the user is passed through this argument here so this what I'm going to do is I'll simply say user or simply say variable user is equal to this object then we can cast it to a user type so simply say as user now there are different types of casting you can actually cast it by simply using parentheses so I can simply do this then say user that's also a form of casting and this will do right so now that I have this user what I'll simply do is I'll get this user and I'll check if the user's name so simply say name if the user's name contains a specific text so where do we get this text from well right here from this text box and we give this text box a name we said filter text box so simply go back here and I'll simply say take the text from the filter text box now there's another feature that I would like to add and that is I do not want it to be case sensitive so if the name has an uppercase letter it shouldn't recognize the uppercase later or if it has a lowercase later it shouldn't recognize so I can add another argument to this contains method and that is the string comparison argument so here I'll simply select the NM which is the Arduino ignore case so this is going to ignore on whether the letter is uppercase or lowercase all right now this contains method is always going to return true or false now here we need to specify the property we are getting from the filters text box in this case it's the text property all right now this method as I said returns a Boolean either true or false so if the name contains a certain text it's going to return true if not false now we can actually return that same Boolean to this filter method so simply say return whatever answer is coming from there so this way if this user object has a name that contains the text then that should be part of the filtered list so that's it now let's go ahead and run the application all right so the application is up and running so I'll start by adding a new user so simply say Jamie and Jamie at one two three all right so we have the user added to the list now here I'm now going to perform a filter so I'll simply say j and there you can see the two names so if I say a then we only have Jamie and it doesn't mind on whether I use lowercase or uppercase letters all right so there we have it now when adding the user you notice that this window pops up right here on the left side I would like this window to pop up at the center and should be the child of this main window so we can actually achieve that so to achieve that we need to go to the logic of this main window and to do that we need to go to the view model of the main view so let's go now here this is the logic that creates the new window so I would like to make this window that we created a child of the main View so I can simply set the owner property so simply say owner then I can set it to the main view now here we do not have access to that main view object or the main view so how do we set this on a property to the main view well we can now use this parameter so when invoking a command you can actually pass an object through the command parameter let's go to the main View now here in the main View if we have a look at our button here we can add another property code command parameter so this object will be passed to the logic that will be executing the command in this case I would like to actually pass this very view here as the object now this window here was given a name called main window so simply get this name I'll copy now here what I'm going to do is I'm simply going to pass a reference so I'll say reference then I'll specify the name in this case I'm going to specify this very View which is our main view so that's it now here in the logic let's go back now here in the logic I can access that window by getting this object so simply say VAR Main window is equal to this object then we are going to cast it as a window so simply say as window all right now that we have our main window we can now set it as the owner of this add user window then the other property that I'm going to set on this add user window is the startup location so simply say start up location then I'll simply set it to the center of the owner so this window always start up at the center of its owner all right so let's go ahead and run the application so the application is up and running so regardless of where we place this window if I click this we should see another window pop-up here at the center all right so there you have it so this little window is now a child of the main window just by simply setting its property right here all right so there we have it that's an mvvm pattern implemented on a WPF application now let's have a quick recap so nvvm allows us to separate an application into three layers view view models and models this way we can actually separate the consents of the application so this means the views only deal with the appearance of the windows The View models deal with storing the data and executing the logic and the models deal with the applications data in this case requesting data from the database as well as defining the classes or the entities used in this application so if the application has got a problem maybe we are trying to fix a bug we're not exactly where to fix why because it's easy to navigate through this type of project structure if the user needs to add a new property or simply open the user class and add a new property if the command has a problem we simply open this command and fix that problem all right so there you have it thanks for watching this video remember to subscribe to this channel if you find this content useful I'll see you in the next one
Info
Channel: Tactic Devs
Views: 19,043
Rating: undefined out of 5
Keywords:
Id: 4v8PobcZpqM
Channel Id: undefined
Length: 43min 46sec (2626 seconds)
Published: Wed Apr 26 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.