WPF in C# with MVVM using Caliburn Micro

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
WPF is a really powerful front-end framework when people start to use it typically they just scratch the surface of what I can do today we're going to dive a bit deeper into the power of WPF by implementing the MVVM pattern specifically we're going to use Caliburn micro as our mvvm framework we could do mvvm on our own but that feels a bit like building a car before driving while both are fun activities I think it's more important we learn how to drive before we learn how to build the car later if you feel comfortable and if you really want to do it you can build your own mvvm framework now if you're new to this channel my name is Tim quarry and my goal is to make learning c-sharp and other related languages as easy as possible for you if that sounds good to you hit the subscribe button to hear all about the videos that I release if you feel like you might want to go a little bit deeper there's a link in the description to a mailing list there you'll get insider news and discounts on the pave courses I provide all right so let's jump right into this topic let's start off by setting up do PFD is Caliburn micro so we'll start our going to create new project we'll select visual c-sharp windows classic desktop and here the very top it says WPF app dot net framework so make sure this is the one you have selected not a different WPF for example if you just search for double pronto for the dotnet framework in visual C sharp now let's call this WPF UI a lot the big acronym that's okay that's the project name our solution name let's call it cm demo for Caliburn micro demo we'll hit OK so like I said we're going to get this set up for mvvm and caliber micro and it'll kind of come back and talk about what mvvm actually means what stands for why we do it and all the rest but let's start with some basic startup stuff you need to do so the first thing right click on references and say manage new get packages and the left up here we'll hit browse and then we'll search for Caliburn dot micro there we go the very first mop is Caliburn dot micro by Rob Eisenberg and all the rest and the current latest stable version is 3 point 1.0 so go ahead and install that we'll ignore the rest of them for now if you wanted to there's other add-on projects they'll help with different things like telluric and all the rest but we just need the Caliburn micro three point 1.0 and it says do you want to review these changes hit ok before proceed proceeding that's cool let's do it we've installed and now if we go to install we'll see calibre and micro and actually calibre and micro core as well the reason we have two packages is because calibre and micro relies on the package of calibre and micro core so with those two installed we can close that out and now we need to do a little more housekeeping on our actual application out of the gate we have the apt sam'l in the main window channel in app dot sam'l it says a start-up URI is main window duck sam'l so app dot sam'l says we start launch this window well with mvvm and calibre and micro when you change that and so the first thing we do is we actually delete main window get rid of it don't eat it then in the app saml we take out this line for start-up URI the reason we do is because we're going to have calibre and micro handle the startup we're not going to have to a PF handler next we're going to put a bit of code inside this application dot resources now you could just follow along and type this along or in the description down below you'll see a link to a blog post where I've put some of these code chunks in place so you can just copy and paste so we say a resource dictionary and then inside there we say a resource Dictionary dot merge dictionaries inside there we say resource dictionary again inside there we say local colon bootstrapper and an x colon key equals bootstrapper and so what this is doing is saying here's we're going to start our application in this case we're going to start it at bootstrapper now the thing is we don't have a bootstrapper yet well we right click on our project and we say add class and we'll call this bootstrapper and now I make this public and we're going to inherit from bootstrapper base in control dot there to add the user statement for caliber and micro and now we have a bootstrapper class we add a couple things here first constructor into a shortcut ctor and tab twice and say initialize and then we have one more rad protected override void on startup instead of the based on startup we're going to display route view for and we're going to give it a view model to start and well let's guess what females are in a minute we don't have a view model yet but let's call our view model shell view model that's kind of like the the base or the standard view model to start from a shell view model it's kind of like main window dot zamel is for the default template and at this point you're probably wondering what are we even doing we're doing a lot of stuff doesn't seem familiar at all and that's why there's a little bit of learning curve when it comes to using calibre and micro or even any mvvm framework in WPF and the reason why is it does kind of change up how we view the application in the forms so let's talk through what this is doing and then we'll go ahead and add our shell view model so the application starts at the AB decimal that happens we're using regular de PF or de PF with mvvm using calibre micro either way it happens the same but if it's a regular DPF app we specify up here the line we deleted is right there the next line down and it said you start up our main window down zamel well instead of doing that we've said since we using Caliburn micro we want to start from the bootstrapper that's our starting point and so Caliburn micro knows how to handle a bootstrapper that's what is designed for that kind of starting point for it so we created this bootstrap or CS to say this is the starting point for our application we inherited from boost revered base which maybe bring all that code in from boots Trevor bass into our bootstrapper and while there's a lot of stuff going on behind the scenes that is a lot deeper than what we're dealing with right now all they care about is two things first of all constructor just says initialize which that's in the boost ever base instead initialize does start up some processes and then it smoother then there's an event and that is then it's called on startup now we are overriding the base implementation of on startup now if you're not familiar a variety essentially what it does it says there's a method in or an event in boots every base called on startup but we don't want that code to run instead if the on startup event gets fired we want our code to run and that's we're overriding that on startup method and the only thing we're doing in here is displaying the root view for this view model so essentially this is we're saying this is what to launch instead of main window dot sam'l as our launch point our launch point for our mvvm application using calibre and micro is the shell view model so essentially all the tweaks you've made so far all boil down to launch this view model that's we all we're doing now we don't have that yet we're going to create that this is a great time talk about mvvm and what that really means so let's start by create a folder for each of the acronyms in mvvm so say add to the root of our project add new folder models the folder where all of our data objects will live now in mvvm especially in calibre and micro that's really left up to us when we need models it's not really based in the framework you have to have models like the other two items we're going to talk about so models you may have no models or you may have a hundred it really depends on how you deal with data and how you talk to your other parts your application so we'll leave that empty for now it will add the next folder and this is views so so far we have models the M the first M and mvvm now we have views so there's a V so yeah m and V we need V M yet so views this is our actual user interface this is where the objects will live to have zamel that have that friend code where we see you know text boxes and text blocks and the grid and all the rest that's where those will live it's inside of views folder and finally we add one more folder and we'll call it view models and this is the V M so M V V M that's the mvvm framework the view models are really the drivers behind the application that's where the code lives that supports the views and so down here and display route view for we call a view model so the shell view model so the shell view model is going to live inside the view models folder the shell view will live in the views folder so if you want to think a little bit simplistically about it which simplistically is good think of it in terms of wind form in a wind form application you have the drag-and-drop user interface the front and we call it think of that as a view then you have a code behind that actually powers that that front-end think of that as the view model now there's some separation concerns come Jana is a little bit more to it than that but at the base of it that's really what it is this is where the code lives this is where the view lives or the the front end the user interface so in our case we need a shell view model so right click on view models to add class and call it shell view model first we need to do is make this public now it's up to you depending on situation if you want to inherit from something and if you go on the Caliburn micro documentation there's a few different things you can inherit from and we can go over those in a little bit but I want talking about what I do as a common practice so I typically inherit on the shell view model which is my based view model or the the foundation I inherit from screen a control dot and a using Caliburn micro and what screen allows is it allows for a little bit more control over opening closing it so I can get events to say hey we're closing this are you sure you want to allow that and we can use that for something like you know if the a form had been updated but not yet saved we could say hey do you want to save this form first before clothing so there's some stuff there that the screen allows that that's pretty powerful so I'll start with that and then as we need it we may upgrade this to even more powerful inheritance but for right now if we're doing just one view model and screens great and that's all you do for our view model now we do need to have a corresponding view so in our views go right click and say add window I call this shell view and actually I'll leave this entirely alone I'm not going to do anything with it yet so at this point let's go ahead and hit the start button and we get an error now this air is actually five different errors so if we see here the name bootstrapper does not exist well yeah it does it's right here and even on the root namespace so why is that problem well actually that's kind of a red herring error it's not actually the air we want down here is the air you want the shell view model could not be found that's because I have to control dot and add the units in it for the view models folder now you can run this again and because this compiles it will find the bootstrapper and it launched the actual application alright so we've actually launched our application if if we expand Tsao we see that WPF UI dot view models dot shell view model is the the title up there so this actually works and you may be wondering how how does it work because it's called a shell view model which is just an empty class why is it launching this zamel form and in fact may be wondering well is it even launching that form so let's do this just to prove that this is the form of being launched the shell view zamel let's change the background to red so this views background is now read if I read start this and start on the wrong screens over and over it's red so it definitely is launching the shelve you let's get that hideous read off the screen so how is it launching this view when I said to start up right here on startup what's going to launch the shell view model and that has nothing in it doesn't have any reference at all to shell view and the reason this works is because of naming conventions so caliber and micro is huge on naming conventions if you name things properly then they will work together so in this case we have a shell view model it's in the view models folder and that's important to create a view models folder not VMs not view model singular not my back-end code always create a view models folder the same abused and sainted models that just allows a naming convention to work a little better now you can use other folder names if you tell it but don't rely on that do like it's designed for and create these three folders so in the view models folder I said that the view models the kind of back-end code for a user interface so the actual name is chell at the end of it is the view model because that describes what it is what thing it does what it represents so it's a view model the name is shell therefore if we're looking for the view that corresponds to this the name will also be shell but it's something different it's not a view model it's of you so shell view these therefore are connected this is kind of like the back end code this is kind of like the user interface now I want a real quick digression here talk about what these three folders represent all three folders represent the user interface this is not a front-end business logic and data access layer this isn't a three layer application this entire thing is the user interface it's just the user interface has been further segmented and that may seem like it's just semantics but it really is important to note that difference because it changes how you think about the code that goes into the shell view model it doesn't have to do all the business logic just the user interface logic in the WPF add-on course for my c-sharp application from start to finish or e build tournament tracker and then the add-on course we actually change the user interface over to be jpf using this caliber and micro we were just replacing the user interface we still had our business logic we still had our data access logic all inside a class library the only thing that we're replacing was the user interface even though we had view models models and views so just keep that in mind that this is still just a user interface all right back on throw a trail back on to mvvm so this right now is the start of our application it's working as if we just started up with the UPF in new templates now let's start actually using calibre micro to see the difference does it see a power of it so let's start off really simple we're just going to put text on the screen so let's create a property in our shell view model we're going to a full property so prop pull tab twice like a string and we'll call it oh it's call first name underscore first name tab again call this first name all right there's our full property let's actually make these getters and setters a little prettier okay so their full property called first name it has a get in asset and that's it alright this is the private vacuum field if you're not familiar the convention is an underscore and then camelcase for our name for a private banking field and what that does it just lets us know don't touch this don't manipulate it directly instead manipulate the actual property that way any kind of filtering goes on in the get or a set can occur so that's in our shell view model the back end code for our user interface let's go over to our shell view now in a little bit we'll set up the grid let's just do it now that way it's a little quicker and easier to do let's get these out of here we'll split that the other direction just so we have a little more visibility in or zamel alright so in the grid have the grid dot column definitions most of the width and normally what I do is I put a border around so I'll just say let's get 20 border and then I copy this and I paste at the end so they have on the first and last column have a with a 20 and then the ones inside have Auto now let's put a few columns in here to stack have a few last one I'll do star so that last one takes up the rest of the space if you're not quite familiar I'm doing here on my youtube channel there is a video for intraday PF that's we talked about the grid and the columns and the rows and setting this all up so they're the same thing grid that row definition I'll start as a height of 20 for that first row and also a last row and then in between again we'll do Auto for quite a few last one I'll do a star alright so that just sets up my grid so we have and I can actually collapse this down so it's a little less space being taken up and now we can start getting to work on putting something on our page so let's start with a text block and we're going to say this is in grid dot row get Row one and grid column column 1 column 0 and Rho 0 are those 20 pixel wide and high borders and so we'll start inside kind of like put a padding around the entire thing now we're used to doing some of this where you say you know testing and it puts testing in a text block and that's right there on screen let's actually change the font size this is what we're here so font size as equals let's try 16 to 18 there you go that's one more readable for the video so that's where you stores having just put the value right in the text block but we're not going to do that instead we're going to say X colon name equals first name sound familiar we have a first name field or property well the nameless text block is first name let's run this and see what happens nothing happens it's empty okay that's good that's okay let's now go back to our view model and say the first name string let's initialize it to a value of Tim and run it again now it says Tim on our form so how did that get there well again it's naming so the property is called first name in here our text blocks name is first name so it said was in the view model the property lines up with text boxes name so since the view model is kind of backing code for this it said hey got a match here connect those two now here's the really important part you need to name things well first of all they should be descriptive which we already know this but it's in more important since if you call this text box one you have to call this text box one which makes no sense conversely if you call this text box one the only links up is if you call this property text box one again no sense so name things well the next is make sure that you're consistent and careful in your naming meaning if you call its first name singular you can't call this first names plural because then you won't line up if they don't line up then it won't connect the two then you have a text block with nothing in it now right now we have a really boring form it just has a text block that shows something from our view model it what kind of kind of cool that's an awful lot of code for just replacing typing in here so let's make a little more of an interesting item so let's say text box I say grid dot Rho equals 2 and grid dot column equals 1 and then we give it a name of first name now it's going to yell at me because it says the first name is already defined in the scope so what if I wanted to hook up both a text box and text block to the same value well they both can't have the same name let's take this one's name out for a minute and now our text box is wired up we'll get back to the text block in just a minute but let's add a width of 100 to our our text box we can say actually here min width instead of width and that's good because with a minimum width we say the smallest of text box gifts is a hundred pixels wide and the reason why it's important is because of the column word to grow so with a text box but at the very minimum it's going to be a hundred wide so that that's going to start with before you anything else the taxbot blocks we empty has no name anymore the text box is name first name and we'll see that it actually fills it in with the value of Tim which is great before we go in further let's go ahead and change this form the properties here inside of this form we look at the window start up location let's change it to the center screen then we should start on this Korean Civ I had to bring it over every time so I just a little please can make let's shrink that back down all right so now it starts center screen and notice I went to the property to do this after clicking up here in window but it just adds a mold right in the screen so actually all does so I could have just typed out window start location equals center screen it does either sometimes go at properties and do it and let's just test it to make sure it's going to work right so I it start and there we go so it starts on the screen all right back to where you were so we have a text box that now has the first name property but we want to also have the text block have that same value so we can do is we can say text equals and we'll do a binding and we'll say path equals first name comma mode equals one way so what this is doing is going to bind to the first name property now it's not giving the name of the textbox the text block is not named first name so that binding doesn't happen automatically through the magic of Caliburn micro instead we're manually saying this is how you bind it up and this is what's going on behind the scenes whenever we name something with a name like this it's looking for that property and saying if there's a property there that's the same name do this for that item but you can do it manually if you want in this case it's a one-way binding meaning that's not going back and forth means not also accepting new input and changing the property so let's run this again and we'll see we have Tim and Tim but check this out nothing happens so if I type Timothy it doesn't change Tim and that's we get into the next piece we need to learn which is the notify property change so we have this full property here and normally have Auto properties there's easier to use a smaller less code and just as a get colon or semicolon sex ni colon doesn't have the returned in the set and the private backing field but there's some real benefits to having this get and set be a full getting set and one of them is after you change the value so it's the set so after the value is changed we can say notify of property change open our print open another set of parens and close it say equals greater than the lambda expression and say first name so what is doing well it's saying notified people anybody who wants to listen that the first name property has changed so really just need to copy and paste this wherever a property changes or this changes the value that also changes a property so first we'll get into a minute but if you have full name property changing the first name would also change the full name so you do a notify a property change on full name as well as first name here but let's do first name for now let's go back over here and launch the application and now if I type oth Y notice my label also updates because I change the value for our property and notified everybody the property has changed it now updates my label with the new value since it's listening for changes and that's where binding really becomes powerful in caliber and micro because we can bind things together in a way where updates just kind of magically happen we know it's not magic we know it's happening but the conventions really help us out and simplify things a lot so let's add another property here we'll do the same thing in fact I'm going to cop down my table you paste copy and pasting is dangerous I don't want to encourage danger so I'm actually going to do the prop full the reason is dangerous is because I have to change first name first name first name first name and first name if I forget say this first name right here it would still notify a property change for first name just not last name that's a problem so much better to do a little bit extra typing give them the end it's going to save you some pain so let's go ahead and in here so expand out this set I don't have to expand both if you don't want so let's say notify of property change open parens twice close the first set of friends put our lambda expression and say a last name so now it's going to notify of a property change on last name whenever last name has been updated and finally I create one more property prompt full that's going to take away the private backing field I'm going to take a way to set and call this string full name and return let's do our dollar sign and double quotes then inside there will do first name space our curly braces again last name like so so first name space last name is our full name so we now have this full name property so let's also have a notify property change in both our first and last name fields that says whenever of Valium first name changes the full name is changed whenever a value of last name has changed the full name has changed so now we can come back over to our shell viewmodel we actually can copy and paste these two let's just copy and paste a text box we don't need to have two different text blocks you can say this is the last name as in column to not column one and then for our text block will bind on full name now we could just name this instead in the binding we just name it X colon name equals full name because nothing else is using full name but we can leave it this way as well we can run this now and now it says Tim is the full name and Tim is the first name because there's nothing in last name but cord and now it says Tim space Cory if I say nope this Timothy now it says Timothy Cory and there we go so no matter what you choose in these boxes this full name is going to update there we go now notice this box keeps getting bigger the reason why is because the full-name is in one column and as that gets larger so does the entire column therefore so is this text box if you want to change that what you do is come over here to your text block and say we can actually put it on second line so it's a little more readable you can say grid dot column span equals two now it's going to span both columns here we start up again you start typing and if we say well as Timothy it goes beyond the border of this particular text box because if spans both of these columns now if you were to really make it big like this day it's going to increase the size of this box therefore it's going to increase the size of this column and if you continue to get bigger it make both bigger so let's see the dynamic nature day PF really kind of helps you out in some ways because the text box isn't scrolling off the edge here unless you want it to we can see a max size in which case it would but without a max size it just makes the column bigger and if this gets too big for the two columns in you'll make the two columns bigger so a lot of flexibility there and I'm not specifying you must be this size then it allows that box to flex depending on the space that needs that's a little off topic for this video that's a little more basics of jpf but I thought I should point out since we saw it alright so we have three different bindings now we have a binding for first name one for last name and one for full name and just a quick note here this source code will be available the final version of it will be available on that blog post as well so again the link is in the description if you want to get a source code of the completed application we build today then check out that blog post all right so let's add one more thing before we continue and that is rad a combobox that's probably something else you'll want to see it's how we have a list of items and bind that up so before we move on to a little more advanced topics in this I want to at least address a combobox so let's start in our view model let the places start for things let's actually kind of crunch this down a bit so we have a little more space here you could move this up this private string up to here if you want or not depend on what you feel is necessary I kind of like to have all the private string together because it just kind of gives them a home to stay together and and I know what not to touch essentially versus mixing them in between all this so that's set up now we can add a list of items well I will make it a little more complicated just to show off the full complexity of what you might do so let's actually go to our solution Explorer right click on models and say add class and we'll call this the person model and they get public and we're going to do a normal model thing prop tab twice first named prop tab twice last name really simple first and last name it's all we're going to do in this person model over here what I want to do is create a new property a full property so crop full and it creates a bind Abul collection of type person model control dot to pull it in using the use exhibit and we'll call this underscore people and I'll start it off the initial value of new so it's kind of empty but initialized now since I do the control dot that messed up my template for the prop fold so I actually could copy and paste this down to where my VAR is I have a change this to be the same type and I have to change this to be people alright so there we go we have a bindable collection of type person model now I know I want to put this into a list of some kind of combo list or a list box and so I create one more full property I call this type person model and we'll call it underscore selected person there we go so now this is going to represent one individual person that's been selected so you choose one person from the list and that's going to populate this property right here and to also do a notified property change in this oops one too many select a person there we go so now we have another five property change on the selected person whatever it changes and we can move up this private and this private variable to their the backing fields so now our a little more compact a little more neat there we go so now you set up both a bindable collection normally called a list but in mvvm you want a bindable collection because it has some more good stuff behind it that allows for notification of changes to a biological collection of type person model and we have a selected person of type individual person model one person model so that's the back end now normally we'd populate this by you know calling database and loading up the objects and putting them in or something like that but we're going to simulate calling the database by in the constructor so let's put constructor here so ctor tab twice in here we're actually load up people so we'll say people dot notice I'm using the actual property not the private backing field people dot add new person model and we'll say first name equals Tim common last name equals quarry there we go and we'll copy and paste that one a couple of times and we'll just change names let's say Bill Jones and Sue Storm all right so there we go now you have three people add to our our list at construction of this view model that's all we're going to do the backend let's change the front-end to have a drop-down so I'm going to add here at the end put a combo box now this little cluttered right now I don't really like cluttered I like a little more space more rows between things what I might do is I might make sure that say over this and right here I would put a comment in here say Row 1 and then copy this and paste it down here and say Row 2 and so on so forth it gives a little more of a definition or a clarity to where things are and says kind of scrunch together that also help me make sure I group things the same row in the same spot this will be easier to look through the source code it's a little bit easier when you're modifying things that looks a little nicer so just something I probably do in fact I'm I'm going to do it here just to make that zamel look a little bit cleaner because as you can see after a while that's crunched up grouped together it looks like garbage it really does it's hard to read and that's a problem because this is not just for the compiler to read this is also for humans to read and so you need to do everything in your power to make it easily understandable for the next developer to come along you don't want that spending hours messing around trying to figure out where stuff is or what's happening especially since the next developer to come along it's probably you and six months after you've forgotten half of what this does or more all right so that's mini-lecture over let's get back to the combo box let's actually start right away with grid Row is in Row 3 and grid dot column is in column one now we're going to give us a name and our name is going to be people that's based upon this property right here so X now notice one thing real quick before I stop before we start again I have it's invalid markup right here since I went away from this page as I was making this modification it tried to re render based upon my changes and it says nope can't do that so if you go away and you have this problem you have two options one is a complete kind of in the dark with this and the second one is to cut this thing out it comes back woohoo and then you can just paste it right back in and continue on because it won't rerender as you're typing out until you either complete or until you go off the page so that's just a little side note in case you see that you for so name equals people so that binds up to the list but now we need to say where the selected item is I should put the next line down so selected item selected item we're going to do that binding again so binding path equals selected person mode equals one way to source meaning it's going to go from this form to the property not from the property to this form so you guys think about the directions either going this one up here was one way meaning it pulled from the property and it kept pulling flynt property it never over wrote the property this is just the opposite it overwrites the property it doesn't read from the property so it's going to set one direction and that's what you want the final thing we need to do I'll put the next line down here here is the display member path and what this is is the property inside of our class that we want to display on our drop-down now you only have first and last name so let's choose first name and we'll close this out so now we have this drop-down on our form and this should have three people in the list we can select from let's run it real quick and make sure that actually works so eyes go to make sure it compiles there we go Tim bill and Sue how we know what Bills last name is well we can actually bind to the selected person person model so let's do that let's put in the same row we'll put a text block grid that row equals 3 grid dot column equals 2 and I'm not worried about padding or anything else like that margins and all the rest this is just quick and dirty to show you how use Caliburn micro not how to make a pre foreign in DF so just clarify that real quick do I know this thing is not looking like a million bucks right now that's okay it's more about Cal it is all about Cal very micro all right so grid row is 3 grid column equals 2 and we'll say X colon name equals selected person but here's the problem if not the selected person you want is one property out of the selected person so how we say I want the last name from the selected person object because selected person is a a people model or a person model object and if we put the whole object there that won't work they'll do it to string and that object and that's just not to help us so we need to do is not dot that doesn't work instead we have to replace that with an underscore so underscore last name so the name of our text blocks is selected person underscore last name meaning the selected person property in our shell view model and then the property inside that is last name and that's all we need to do now it runs again and we see nothing over here but if I select su I get storm if I select bill I get Jones and if I select Tim I get quarry so we've now bound to that last name property based upon the selected person over in our combo box now let's talk about buttons now I love the story about buttons in Caliburn micro I think is the most fun thing to play with in the entire package so let's add a button to our our page so do it row four and we'll say it's on grid row equals four and grid dot column equals one and for now we'll just say this is the clear text button so the the idea the highest button is when you click it it's going to clear the text for both the first and last name fields so is any text in there it wipes it out so let's go over to our shell view model this is the kind of back end code again so I'll collapse down these two extra properties and create a new method and this method is going to have a return of void so public void and let's call this clear text method and we'll say that it depends on right now nothing let's just start off from scratch with nothing just clear text it's all it does and then we're going to say first name equals empty string and last name equals empty string so then click that button it clears out the first and last name properties so over here now I call this clear text that has no relation to the actual name clear text so just to show it doesn't clear name clear names how about that now if the button rest say X colon name equals clear text that lines up with our method name so now if we run this let's put a value in this last one so it was put Cory if I hit clear names it all clears out because that is connected to the method by the name and that's cool that's that's really fun it's neat it's easy it's easy to wire a button up to to a method but there's an even better part to this story so what if we don't want this button let's go back here to submit what if we don't want this button to be enabled if there's no screen there's no text to clear out of screen so if we have nothing in the first name or the last name field while we ever allow the button to be clicked well we have the idea of a can you click it boolean so it be a public bool can clear text and that naming is important because it's the clear text but with can in front of it and returns a boolean true or false and let's just say for right now throw new not in throwing exception not implementing such code that just we have that error off the screen so with this if we return a false the button is disabled if we return a true the button is enabled but this button really depends on knowing if the first name last name fields are populated because that's how I determine if we can clear a text or not so the way we determine or link those two up is a couple different ways one we can turn this into a property and then say whenever there's a change to the first and last name notify a property change on the can clear text property that's one way of doing it but there's an easier way of doing it the clear text is going to check the first or relies on the first and last name so if I pass in first name and last me now notice I'm using a camel case versus the Pascal case of the property so the property starts with a capital F where as a parameter should start with a lowercase F but these two match up in other ways is just the casing that's difference so since I've matched these two up it's going to say well that's actually I pull in the first name property's value into this now you may say well we don't care these are not actually not touched this first and last name that's true if you were to wipe out the value of first and last name instead of this first and last name wipe these out instead it wouldn't do anything because these are just temporary or copied values but because we passed them into the clear text method we can also pass them into the can clear text method and now we can say return and we'll say not string dot is null or whitespace first name and is not string is null our whitespace last name now I want to confuse you so I'm also going to type us out in the full form as well this is the easy form or at least it's an an easy form it's actually even easier form which would be to do a lambda expression instead I'll show you that first and then I'll show you the full version as well so if we copy this and actually comment out these lines as we have them for later but instead do a lambda expression and say that line right there that will when you call this method it's going to return this there's a little one-liner I'm not a huge fan of one-liners just because they are a little harder to read and hard to read it's a problem because code is written for people so just going to think about but it is possible you may see that in examples so this is more of a one-liner that's a little more readable and what it says is return if this is not empty or note and if this is not amp you know so let's talk us through first name if it has a value is it empty or null no so if it that'd be false it's not null or empty but what's not false true so this is a value it returns true this portion does and if this is a value it would return true in this section right here so true and true would return true he asked you can clear the text if either of these would be empty then returned false which isn't really what we want we want more of an oar and what that says is if this has a value then it returns true or if this is a value it returns true if neither has a value it returns false so that's more you want but you see how tricky that was to diagnose and make sure you get right it honestly for me it's just really hard to visualize what this is saying and so instead what I typically do is I say something like this if string dot is one such way that the capital string doesn't really matter if it's convention it you can do lowercase or uppercase for string so string dots is null or whitespace first name and string dot is null or white space last name return false else return true now you see I flipped that script a little bit because that can be really tricky I might not notice it I might you know trance figure out okay are not false is true it again this is my preferences because for me it makes a little easier to be very explicit and I'd probably even comment this so if this is null and this is null or empty return false I mean you cannot clear the text because they're both empty otherwise one of them at least has a value therefore return true so again I would comment this probably and say exactly what it's doing but at least there it's a little more clear a little more straightforward and yes just returning false or true out of an if statements that can be done much simpler in one line but it might not be as readable so that's again a little rabbit trail but that's kind of my best practice is to make it very very clear because if you're reading a list especially quick you might get that mixed up or like I did with the ands and the ORS I got the end mixed up with the or so just a little easier but that whole rabbit trail aside we now have clear text and we have can clear text they both pass in a first and a last name simply pass it into the clear text we can also pass into the can clear text we can't however delete them from here and just take them in here so would that be the case if we start this now nothing look Lee has change because we can still clear text but check us out if I click this now even the button is grayed out but if I type in here just one letter all of a sudden this button is is ready to go again click it it's now grayed out because it's cleared out by type one letter comes back but if I delete that letter the button is disabled again so it's a very dynamic very powerful form the kind just works on its own you don't need to tell it all this stuff to do it really comes down to just whatever this can clear text method says so it says if it's true or false to enable or disable that button so that's I think one of the more fun things in the EPF with Caliburn micro is those buttons that enable and disable although the linking and the binding is is previously as well so so far we've talked about one form just does one form here but what if maybe you wind to have a second form and that's one of the things where demos often stop they show you one for me like great but that isn't helping the real world so let's talk real world from it so let's start by saying we want this this is kind of the parent review the shell view so we want to put inside here and kind of think mdiform if you're familiar with that with wind forms where it's kind of like the the parent-child relationship you have you know your overall forms and inside that you can have multiple forms you know displayed kind of thing it that way in this case we can have one form inside here down below our button so our buttons on Row 4 and we have let's look at the rows which expands out we have 0 1 2 3 4 so row 5 & 6 so we'll have why should put on 5 & 6 watch I feel to take out row 6 essentially so Row 5 is that star row so rest say this will be a Content control and we'll say grid dot Rho equals 5 and we'll say that grid column equals 1 and we'll do a column span so grid dot column span equals 5 will be those five columns we want expand let's give it a name so we'll say X column name equals active item and I'll actually put this the next line down just we have it down there and then we'll close that so active IO is actually going to be a key word for us it comes right from Caliburn micro and that says this is the active form the active child form so you only have one form it's called active item now I'll show you what I mean by one form in a minute so let's add our comment here row 5 and so this would live down here notice it kind of highly just a little bit my mouse over it saying all these boxes right here so that's our active item now let's go back over to our shell view model and let's actually create two methods it will wire the buttons will put the buttons back on the front page before you go too much further let's put create the methods first we're going to say public void load let's just say load page one normally wouldn't have something so explicit like load page one but in this case it's just a demo if this is the real world we could do something like wiring up to the combo box so if you click the button may just says load page something like that what would happen is based upon which person was selected it could load that person's page we're not going to do that but that's a possibility so it wouldn't happy tied to just one person or one form Amin it could be tied to a number of forms depending on a selection or some type of input criteria but for right now load page one whole round do and in here it's going to say activate item and right now there's nothing in my control dot list that allows for activate item that's because we're using this screen as our implementation we're going to or inheriting from screen memorize at the beginning that's good for now but we're going to I change that and that's because screen really talks about having just yourself to worry about just this form but this form is going to worry about itself and one child so instead we're going to hair it from conductor now we have to give it a implementation or an object a conductor of T is called and what we could do here what some people do is they say well any page that can be brought in as a sub page or a child page has to implement a certain interface and so you'd say you know I screen or I child page or something like that and the interface any blank it does has to you know all implement that interface but we're not getting that complicated we can just say object because guess what everything inherits an object therefore everything can go into this conductor so this conductor is going to say you can do this activate item so now activate item is there and it says okay activate is going to put that whatever object to give me into the conductor now I'm going to leave it empty for right now we don't have any to get it now have a form yet if a comment is out just so we don't get yelled at but let's talk just a minute about this conductor so if you get a Caliburn micros documentation which is tough some type of some of its old and some of it's really dense as far as it uses words that I'm pretty sure English but I'd have to look up their definitions and it seems like the definitions have to come from a tech manual not from the dictionary so I can kind of top a time to read through but they do have a page on the different types of shell viewmodel inheritance and you know it starts you can start from screen something's simple but it's conductor of object or conductor of tea you can also have one where it says you can have multiple objects and only one is open or you can have multiple objects and multiple or open so there's different options here we're going to use a simple the simplest is you have one object and that's it one child at time so when we ask for a child it creates the child and puts it in the view when we change children maybe change which child view is there it's going to first destroy the old child close it destroy it then create the new one input in the form then we're done with that it's going to close and destroy it with the multiple it will close them but not get rid of them so they are disabled there they're no longer active they're deactivated but they're still in the available objects list and then with a multiple you can actually have multiple active at the same time so you can see how it gets a little more complex each time and a little more to work with but also a little more powerful each time we don't need all that complexity we just need one child that's all we need at time so therefore we're going to do conductor of type object now we're activate one item at time so let's come back over to our solution Explorer and actually create two new view models so add class and we'll call this our first child view model it'll make it a public class and one Herot this from screen the control dot for the Cal bear micro you can fit it and we'll do one more second child view model make it public and will inherit from screen when I said screen is kind of my default for the place I start from for a view model now there's nothing in these two view models and that's okay the names aren't great and that's okay as well I just want to have two more pages I can put onto my or two more you know views so I can use as children to my main shelve you so now you need to create the corresponding views for these view models so right click and say add and I don't want to add a window I want to add a user control user controls are for inside of other windows they can be used on their own but they can also be used inside another window windows can't be used inside other windows so that's kind of the difference there now there's other differences behind scenes with APF and and you can go through all those and more just the APF centric course but for this case we just need to know that our main view model I says a window everything else I use is a user control so now I first need to control the first child view now this has nothing right now so let's change the background color to be blue simple then let's add one more view so a user control I'm going to call it second child view and we'll set this background color to be let's do green not grey grey is awful green there we go it's super bright but it's definitely recognizable adds a second view so now we can save all this and start closing out the stuff we don't need now in our shell view model when you say activate item it's really simple new first child view model that's it now why new first child you model well we create a new instance of a view model instance we're activating an item caliber Micro says okay that's the view model then I know the view must be first child view it wires everything up let's create one more public void load page - and we'll say activate item new second child view model so we have two buttons one says load page one one and says load page two each one will activate the corresponding view model and since we're just activating them the active view model goes in this active item content control so that's we all there is to it so let's just put our button on the form and in fact I'm actually going to add that row back in so I'll copy and paste I'll put this on row six not five so I can put the buttons right above it so say row five and in here let's take us away I want a button and the X colon name equals net name was going to be load page one and I already care at the market that's fine and for the actual grid dot row we need to have five and four grid column or si one and we'll call this the load first page button and then we'll put another button here X : name equals load page to grid dot Rho equals five grid dot column equals two and we'll say load second page there we go and notice how it's squishing off the edge it'll actually make those columns bigger because of it so if I hit start now let's use a little bigger here load first page check it out blue load second page now it's green also notice look at the size that it takes up it seems kind of perfect right well that's because the APF handle the idea of changes in width really well we haven't said this is how you're going to be instead he said take up all the available space in this last row and all the way across including the last column except for our nice meet 20 pixel wide border all the way around so now we can load different forms on our main form depending on what our needs are from here you can make a really powerful application just the pieces I've shown you some people for example might say we're not gonna have anything here we're just going to have these different form views and they a menu so you can select you know load people and it's going to load the people page and then maybe the Nullah it says load tasks and it loads just attacks instead and so the whole page is nothing but child forms or all the people will say right how our standard information up here but then based upon what you select your what you do different forms will appear and disappear as needed so the ton of stuff you can do with this if you want to see more of an in-depth on DPF using mvvm and Caliburn micro and boys a mouthful but you want to see more of that there is the add-on course for my c-sharp application from start to finish course so I create Adam course where we use calibre and micro to create a new user interface that is a little more powerful more dynamic than our wind form application was or wind form you I was you're placed at UI with a calibre Micro data PF UI that it's a little more powerful a little more fun and so if you want to see more of a real-world application for this or how to use it that encore and course is probably the best place to go that I can recommend alright so I hope that you follow along I hope that you've kind of kept up with what's going on you can definitely download the source code from that link in the description we're on the blog post you can also leave me a comment down below and say you know either I love it I want to do more or you know I'm how lost on this or how would I ever use this all depends on on where it hits for you so let me know also appreciate a thumbs up as well if you appreciate the video thanks so much and as always I am Tim quarry
Info
Channel: IAmTimCorey
Views: 343,817
Rating: undefined out of 5
Keywords: .net, C#, Visual Studio, code, programming, tutorial, course, training, how to, tim corey, C# training, C# tutorial, caliburn.micro, caliburn micro, mvvm, wpf, vs2017, visual studio 2017
Id: laPFq3Fhs8k
Channel Id: undefined
Length: 83min 30sec (5010 seconds)
Published: Wed Aug 09 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.