C# WPF UI Tutorials: 13 - Complete Page Animation

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] okay so in this video we're going to do the page animation finish off the page animation where we slide between pages so the login page you'll slide out and the register page will slide in for example whereas right now we just have the secondary page sliding in and the first page just disappearing so that's what we're gonna do in this video I keep seeing this pop up every now and then basically zamel doesn't really like Generic see if the work hard at getting it to accept them and I keep seeing this hovering off whenever we're using anything that involves our attached properties because they are generic attached properties that we made so let's just fix this first you can see the issue here says it violates the constraints of parent so we just go to and in fact if we use the shortcut ctrl T which is easier that base a touch property and there it is it's complaining about this because we are constraining it to a generic type and that's perfectly valid but the problem is sam'l is no good at handling generic so it just doesn't like this part here so let's just delete that part and you'll see the issue we then get which is only really a small one which is that this instance now doesn't have that on value change because it's just an instance of whatever the parent passes in which will always be a base a touch property because it passes itself in so we know it's going to be this because we're going to abide by that rule anyway so let's just copy that delete it from there and then we'll just fix those small issues by simply ctrl click on the instance and paste the type in back now let's not do that let's just do instance as that our mighty instance hours left and the same here object locators definitely working now because it's changed to object references not such an instance and object well the only way that could happen as if this instance is not which I'm guessing somewhere behind scenes that WPF is making this content not be a current page so maybe it's no which I think it will be by default so at some point this is gonna be not so it's just had a question mark here and then that should fix the build a shoe with attached properties never let's cover to that build issue we have another one here cannot read page properties because it's not in the tree with window is root which it is so again I think this is just an issue with it dynamically doing a value converter to a page into a frame again I think WPF is just struggling so we can tweak this the way we do this content so we can override it at design time so at least we get rid of that error so we'll do it you need to change to a date contact so that we could do a design time data context of nothing to fix the error which that should actually fix the error oh it will when we finish this so let's move all this into a data context and then simply bind this to the binding and so what we've done now is shifted the data context of the frame to be the page and we've simply bound to that so we could move the converter out into here but to be honest there's no real need of this works let's just run the application now and see if that still works yeah so that sort of fixed the few design-time visibles we were seen and the only downside there's you don't see a page in the main window frame but that's fine we can see the page if we actually open up the page tribulus predator you know login page or went to the actual login page you know you can see it there so i think it's just that WPF isn't quite as as capable of handling you know the complicated situations with very Natick to see it all at design time so that fixes the design time issues we were having the one thing we've also got to do of just thought let me just check what we did with base a touch property them where we calling no I think that's okay yeah so we should be good there so now let's just fix the login view model change you back to you navigate into the register page and let's see of this so this still works so the next issue we've mentioned is this navigation page up here the navigation frame or navigation bar whatever you want to call it and we don't want that already and a handle our navigation in the view models so we need to get rid of this this bar at the top that will be done in the frame wherever you are here I think I need a name there I think it's called navigation UI something navigation new add visibility hidden and that will well should get rid of the bar which it does but you'll also see we've if you press alt on the keyboard and press left you'll see we navigate him back so you can navigate the navigation still there so it's not quite a complete fix so we need to clear the navigation history every time we navigate to keep it as a you know non navigation so because that involves code behind to clear the frames navigation service every time things change we'll just use an attached property so in the attached properties let's just copy say bottom attached properties copy and paste we'll call this one no frame history I want to get rid of the frame history the no frame has to be attached property for creating a frame that never shows navigation and keeps the navigation history empty remember to pass in the class itself and it's going to be a true which is fine well override the Haan value changed and we first need to get the frame that we attach to so that would be our frame equals and frame we might as well do this so we don't have to attach that as well so Kings the navigation UI navigation UI visibility equals hidden hide and navigation bar now we also need to clear history whenever we navigate so I'll say clear history on navigate for that we'll just do hook into the event handler for when it navigates is navigated so when it's finished I'll just add an event handler right here it's give me a nice and short so we then want to do sender here will be same as this cool you've got to send her in an event so the sender is going to be a frame again so cast the sender to a frame and then we'll say navigation service dot remove back entry which removes the last navigated history so basically whenever you navigate you clear that one that you navigated to from the history so this just simply constantly keeps a navigation history empty and that's it that's our attached property so we should be able to now attach that to here [Music] like that I think yep and now if we run and we navigate and we press Alton back Alton left rather you can see there's no history we can also temporarily just comment out this line so that we can see the bar to see that there's no history so you see we've navigated but there's no no history there let's fix the frame so now we want to in order to navigate and animate two things at once we're going to have to have two frames because we need to animate that out while the next one's animating in we don't want to wait for that to animate out and then change to the next one so we need two frames to do that also the other issue is we can't bind the content directly to the frame because that's a current page and the binding and more importantly the value converter a synchronous so you can you can't sort of a wait for the previous frame to finish and move to the next frame or set the other frame but actually we're not going to wait for the next frame we're going to set you know set another frame and then move on but either way I think because we want to keep it clean we want to just be able to bind a control to the current page and have it simply you know navigate to that page and animate the previous one out I think we'll turn this into a user control so let's go and go into controls let's add a new user control and let's call it I don't have page host or something change the namespace here remove the controls word press f7 remove the controls from the namespace clear all the unused stuff clean on this there's also a new way of found to wrap things in a region so instead of type your median constructor and then going down here in hand region what you can now do is simply select the line below all the thing you want and the line above press ctrl K and then with control still pressed you press s and that's for command surround it shows this pop up then tap down twice and press ENTER for region and now type the name of the region constructor I've only just learned that I can't think where a spotty Deborah spotted it being done I think it was when I was looking for a shortcut for wrapping something and I read that you can press ctrl s and it wasn't actually for wrapping regions it was for something else like one of these and there's a spotted region in the name so of all the years I've been doing it this is the first time I've realized you can do a lot of shortcut to wrap regions so you can remember it it's ctrl K and then S which is command surround by because it's to surround some code so that's the constructor then in this control we want to just have a grids fine because we want to overlay each other just want to have two frames one with an image they all page and another one with the name well that's also add the local note frame history dot value goes true copy and paste swap one called new frame a new page so we just have two frames and then whenever the current page changes we will update the new page and just before that we'll check of the new pages already got a value from before you navigate away set it to the old one and animate the page out so if we now try to use the page host so we change this to local page host on that grid you no longer need that will keep the data contacts the same and [Music] content is now not what we wanted only the background transparency tertius so the issue we have now is we're not afraid so the content won't work well I think it would work we just simply replace the content you know wouldn't do so you know can't create instance so we want to have like a property like this called current page and to do that this is a dependency property so if we go back to the page there's another shortcut again the dependency properties are almost identical to attach properties it's just a different way to register them and unfortunately they're also just as messy so if we do again there's a shock of this type drop and you'll see these little dots with a square around them this is like a code snippets this is a helper that inserts you know predefined codes like prop age and tap twice at insert a dependency prop an attached property the one we've done previously and then you'll see from that prop DP which stands for property display dependency property so type in prop DP and then tap twice that'll insert a value you can see it's highlighted here in blue which means it's ready to type and replace all the instances so we can define the type while the current page needs to be a base page and you'll see the issue we've got here as the base page is currently generic so we need to go and fix that so let's just presume we'll fix that in a moment and while we're still in this the gray means there's something else to change as well so while you're in the sort of dynamic creation mode blue is where you currently are which we've now changed and you can see it's changed base page well it will change this into here and listen to you when we tab and now it's also moved over to the next thing which is the property name to change and it's going to change here where the red dots and here and here and you can see this is actually a name that includes property at the end so but it's smart enough to you know change the name only at this point in creation so we create the name now call it quorum page and press ENTER then you can see change this to current page property that's the current page this control Dottie doesn't know where that is dependency property type of base page we've got a fix and then here's the other thing you need to fix the type of owner class it's saying a dependency property has to be attached to you know a dependency object which in this case is our page itself we want this property to be on this page this page host so in the type of owner class paste page host this will change this is the default value right now which is an integer still it doesn't really fix that so we'll change that to a UI property metadata and in that I think we can pass in an event and they'll call back for some when the property changes because we want to know when the current page changes then we'll update the frames manually so this can be current page prophet he changed control dot and then enter to generate the method for us let's just move this out and tidy this up a little bit so read your own property change events called when the see quorum page by has changed and then we'll implement this in a moment comment this and Z my again this editor config I talked about previously as complaining because this can be instead of doing the curly bracket you can do a shorthand version like that and then remove the keyword return and then the same here and also a quicker way of doing that as select anywhere where it's read control dot and enter and you won't get these warnings yet I'm going to commit this on the next video this helper editor config file or maybe do a short video on it so you can tweak it as you like and it sort of forces these these hints to make the code shorter everywhere all all places you can do things easier it sort of shows an aerator to force you into doing it as a standard it's just something I made up and applied so that we always keep our code as clean as possible so a dependency property consists of this register call which is very similar we take a look at the plate attached property you'll see here value property that we made dependency property don't register attached there's a name a type an owner and a UI property and here it's exactly the same so we have a name a type an owner and a property the only difference is that you call register not register attached and then the back in thing here there was a value which we did get value set value with the keywords getting set before we simply get replaced by doing a public property which causes it to have functions called get current page and set current page anyway so this is very very similar to an attached property but this is the way you do a dependency property and again I don't like this because now you got to define two things I also don't like this it's hard and I don't get why the code snippet isn't smart enough to do this but instead of having a string that says current page then we go and change this to current page - this is now never gonna work it's not updated so change this also delete the string and type name of current page and that'll simply convert this to a string but now I've really named this it's going to rename there as well so it's never going to break so that's all the dependency property is again I'll probably go over this more in another video maybe on just dependency properties but really a dependency property is just about getting a public property to be settable inside of a saml so we can now do say in in this window this will now start working when we compile we can you know we can actually set it as if it's a value of property on a control inside of sam'l so this is just a property as simple as that we tell it to fire this current page property changed when this gets get they're set to a different value so we can even do that in code like in here we could just say current page equals a new login page and BIOS setting this here we'll get this fired here so it's like you know it's like putting a value inside the setter but you can't put a value inside the setter directly here because of how dependency properties work it wouldn't work that way so you have to use this sort of syntax to turn this into a property that can be accessed in sam'l and in code behind so we've got the property there just change this from a normal comment again I don't get why the code behind doesn't do a proper comment registers current age as a dependency property so there's our dependency property let's put a space there let's wrap this control KS region and we'll call it dependency they would spell it wrong depend and see properties have to really think that word out so we've got the dependency property for current page and it's going to be a base page which we've got to fix at the moment and then when it changes we'll come back to that in a minute so let's go and just fix this base page because this could be of any page it doesn't be a login page it could be any kind of page so let's just go to the base page first and take a look at the issue so we're passing in a view model prior primarily so we can have this view model here so that any page can do just you know this dot view model and get access to its view model which is handy and also when we set it it sets the data context so that's the reason we pass in the view model here but everything else about the page and what we care about is the animation in this case has nothing to do with generics so it doesn't need to be generic so what we'll do is strip out the generic part and create a separate base class so that we can at least access the animation of the base page so let's create one above just call it base page there's gonna be a regular page a base page for all pages to gain based on finality so same comment a base page with our deeds view models support this one's gonna become this is now gonna and have it from the standard base page the non-generic and then we can just move so that's a goddess takes it's the VM public properties we can move everything except the view model so let's select all those cut everything and the public properties except the view model and let's paste it in there select around KS region public properties so all's we're doing is moving off you know what was in this class down into the base class which were override in anyway so we're not losing any functionality we're simply moving everything we can into this non-generic class so that we can use this as a standard variable without knowing anything about a view model that's a public property done constructor sets up these two things which are in generic so let's just copy that constructor delete that out to this one make sure we call the base which I think it does by default anyway but I like to explicitly call the base instructor so it's obvious that we're also gonna call this constructor paste the entire constructor again and this time delete the opposite side delete the view model path and now we want to move the function so let's just carry on and that'll fix itself it's now the animation that's nothing to do with view model so that can all come with us so let's just cut that entire region and paste it here and that's all fine and now I think that's it so we've now what a base page that we can access the animations with and we've got a base page that can pass in a view model that then simply adds the ability to have the view model set and that's all that addition does so now this shows here which is what we want we've got a current page and then we've got this that will implement so we put a breakpoint here and let's compile and I think they should just compile fine now hips that's compiled successfully so if we press f5 to run it all runs fine we've now got to oh I think I lost my breakpoint but we put a breakpoint here let's rerun that we should hit this breakpoint there we go so we're getting fired with this dependency property which is now telling us to go into the login page so at this stage now all that's left to do is to first you want to get hold of the old and new page that's in the samel here so that's all the new page so we want to do var new page equals we know the sender is ourselves so of page host in fact there's kind of no point in sending because it is ourself it's simply going to be old a new page so it's nor that bit once got the old page content in terms of before we change the new page what we're now going to class is the old pages content it's gonna be the new page oh we do actually need to do let's go back a minute we do need to this because we're in a static method so we do need to use the sender to get hold of ourselves so send that as page host dot new page let's get the new page first and the old page so these are the frames probably in fact we should probably call it that new page frame old page frame sender is not called Sanders it's called D in this case and say get the frames now we've got the frames you want to get the old content which will be the current pages content so store the current page content as the old page so var all page content equals new page frame content that then we now want to first clear the contents of this page because we've stored it here we now want to empty out this new page to move it into the old page so remove home page from new page frame and we'll simply do that by setting the content to no then we'll now move the previous page into the old page frame so we've got the old page frame dot content now equals the old page content which was originally the new thing so all's we've done a stage as we've shot the contents of whatever's on the new page frame and move that into the old page frame which is simply stacked on top of each other so visibly we shouldn't notice anything it's just that whatever is currently set to this pages content will now be in this pages content and that's what this is doing so now we've moved say in this case if we're on the login page and we go to the veg to page this will be the login page becomes the old content the new frame becomes nothing the old frame is now the login page and then we want to animate that page out so we need to say animates out previous page so we have old page content isn't equal to null or if all page content is base page first because we know it says but we have to cast it and call that old page if it is that and the old page doesn't it well we don't need to do the null check that out and then simply do oh yeah we do actually cuz we're gonna do a task so if it is a base page and if it doesn't equal to null which nope we won't need that when you think about the logic because if it's null then it won't be a base page it doesn't know what it says so this to fail so all you need to do is check of the base the old content is a base page effectively that will mean that it doesn't know otherwise it wouldn't be a base page so we know we've got a base page now so we know we had a previous page in that case we can then animate this out so old page contents on the old page now as it's the old page content does a base page so that we can access the animate function to animate out and that will animate out the old page notice we're getting a warning here so she's telling us were calling an asynchronous method so it ends where they sync so we know that but we're not awaiting it which we don't want to anyway because we don't want to wait for that to animate out before we start animating in the next page so to get rid of that warning we simply tell it to do a task and control dot to find the namespace task run you get rid of the brackets and pass it the actual task to run and because that now is designed to not error out when you're tying it to wrong cuz it's explicitly saying run the task it's obvious we're not awaiting it gets rid of that warning for us so even though they both return in a way table tasks visual studio won't complain if you tell it to run the task because it's a you know an explicit declaration that we know we're running a task and we're not awaiting it so that will then just animate out the old page and instantly carry on to here and then all we need to do is now set the new page content so now we just do new page frame contents equals whatever the new value was passed into this property changed and that should be it so we press f5 we should see the login page appear which we do so let's just first step through and you can see what's happening so I'm first load the current property has changed via which you can't see in the call stack but it's obviously changed by the if we go through a step by step you have this page host we bound the current page to binding and the data context of that is this so we've bound to the view model locator which finds the application view model and the current page which if we go to application view model you can see here so it's getting this current page as a login that gets passed into current page then the current page of here is a dependency property because we made you know we created it here and every time that gets changed which it just did it calls into this current page property changed which is where we are so that's how we got to here first the value is y new value in concedes login page so we first got the new page and the old page frames from this page so we've now got hold of these two frames the old content right now I'm guessing should be null which it is because there is no page at there when you first created this this hasn't been set to anything so it's no so there's no content we clear the previous content which is no anyway but doesn't matter then we move the previous page content into the ologies still no but that's not issue so both pages are still mall right now with an animate out the previous page if it isn't null and if it's a base page which in this case it's null so this won't ever run and then finally we set the current page the new page to the login page that's the first run we click again and let's just disable this so you can see the animation of it works first so we click this and what should happen as this should slide out because this line of code here will run and the next page should slide straight in which it didn't do so let's see why restart while didn't need to restart that book oh yeah did actually so there's the first run so we click this so we know that all works get the old page which is the login page we expect set the new page to know which is just not updating I think in the intellisense here but it will go to know the old page is null get set to the new one so again these contents because they're on the UI thread they need at least one cycle to update so the intellisense are saying that these are still the old values but we know they're not because we've seen the other page on a meeting we get the old page and we do tell it to animate out so let's go to the animate out and hit here so we are hitting the animate out and we are telling it to animate out ah I've just seen a interesting things Eve down here we have got both pages because there's the text underneath for the other page so if we've got that other page let's take a look at the base page constructor let's make sure it's not creating another page just shouldn't do so base page we're creating a login page that's fine we run that so when we hit this we should only create a register page the login page should never get recreated so that's created a register page you can see down here so that's fine and then we hit that so we haven't recreated the login page yet the login page is there and I suspect it's animating in again so hmm why do we go why were we so in the base page I wonder it's getting reloaded because we're changing the content wonder if it's firing that's lousy I bet it does actually it's put a breakpoint here I've got a suspicion that by moving the page the login page to the content of another frame it's going to reinitialize because it's been set as a content it's got to now reinitialize that page to its new host so I think by doing this line here we are firing after we've come out to this call we're gonna fire this a loaded event again and then it's animating in which it makes sense so we create the login page and then we add it and it's been loaded which is what we expect the first time around but let's click it again so create the register page we set things up so we've now loaded one page not sure which one this is register page yeah and I bet that's yep so the login page is getting the loaded called a second time so what we're gonna have to do is we're gonna have to animate out in this loaded call because it's been loaded but we've already told it to animate out and we know we hit that because we got here so we still need this function because that should be called in other instances when you can animate out but in this instance where we are moving content there's no point in doing this we need a different way of handling that situation so let's create a new public boolean short animate out I'd like to indicate if this page should animate out unload useful for when we are moving the page to another frame so shut out a mate out all we need to do is set that to true and then move change this logic so I'll page dot should animate out it was true and will comment this animate out previous page when the loaded event fires right to this call due to moving frames so we set this flag to say okay animate out and now in this loaded event we now don't need that break point in this loaded event we can say if should animate out oh wait animate out how to animate in so if we are set off the animates out unload and makes out otherwise animates on the page so now the logic changes slightly we tell it that that's true and then a students react to this function it fires the loaded event and then the loaded event I'll now know that we expect to load out and it should animate out so there's a nice little example of some debugging for you there and how we figured out the you know what was going on and they just really investigating suspicions and putting breakpoints and places and you know tracking things through so there's the animate in so let's click it hopefully this should now slide out in the next page slide him oh that was nice that worked he's it was subtle because that's a sign off the other one so sign-in that's all it does right now let's just run that again and that looks really nice things a little bit slow maybe it's let's just speed up the base page default animation speed to say half that so it's twice as fast and that's nice so that's a that's a nice speed we can then also add miles well link this button in on the register page but and that we've got a register view model so let's just make that now view model your models open core walk in with you model copy and paste oh I know we didn't rename this bus here just go ahead and rename that to the same name and then back to login view model change this to register so this is the copy class remember not their original the view model for a register page or register screen base view model email login as running change that to register is running well obviously out more in here potentially but for now this East we can't really finish these view models until we've done the website so we know exactly what we need to actually do login command register command struct register view model now register will be the one that takes in these need to swap around register command logging commands simply going to navigate to the other page so it'll be a login and this will be register the login async will now become the register attempts to register a new user register is running away blah blah blah so you can simply do that for now and this will be the login takes the user to the login page current page is login and that should do that's just a basic copy and paste of the login view model just renamed and swapped around so they are functions do the opposite way around we name the class file to the same name as the class then I think the register page needs binding to it as well yeah so I need to bind this to the register view model now we have one go to the code-behind we'll get rid of all these unused ones and change this to the register and what you complain about we don't have different base classes base page register view model register page yeah I got I think it's just needs building yeah so that's now built it's now gonna register view model this is linked to when you click this button it should be the little login so we need to link this button to the login commands to go to the login page so command binding login command register needs to change the register command is busy except to the register is running and the element is the page yep so that's all I think going to work there's a sign in page swipes over to the register page register should spin for five seconds and then just go away which is that register is running command and then this should take us back to the sign-in page we should also there we go we've now got a never-ending cycle between the two pages let's now take it one step further so this is this is effectively now complete and we should be able to resize this to maximum and it animates all the way out which it does and yes so now we want to we're trying to get this application as complete as possible so that by the time we come to do the web server when we have to stop this and move to the web server and then we come back to this this is really as complete as can be that we just have to link it in with the server so now this is a full-blown login page we haven't done the logic to actually log in because we need the web server but now the animation and the page swaps complete and going back and forth between those pages is complete and this is ready to accept the function and the same as this is ready to accept the functions so this is all fully complete we should now start at the application and sign in mode you can swap between the two we can log in once we've already logged in we'll then store information in a configuration file or you know a secret location or somewhere we'll store the details about the the login so that when you first open up instead of going to this page you could check if the users already signed in and instantly take them to the you know the application but we'll do that in another video so this is now complete on these two pages so we shouldn't have to come back to these two pages so now we're gonna add plus at least add a dummy so when you click the login button it waits for say one second and then we'll go to the chat page which we haven't really done anything with yet but we'll also slide the menu in so let's go to the close all these windows know a lot loads open and the chat page is blank so I'll just add something to that so just add a text block text hollow for Seto I can't see anything it's up there in black so let's make the again let's just purely temporary so let's just make anything for now horizontal alignment Center vertical alignment Center font size font large just literally put it edit text in there so we can see something that'll do for the chat page so we have the log in view model when we log in currently we delay five seconds let's leave this in as a hint for later on of how we get the password and email change this to delay for one second and now go to chat page so we'll probably add I think we'll add later not right now probably in the next video instead of doing IOC dot while we'll still do I see a gap for getting the application review model but instead of doing current page and setting that we probably want to go to page function in here so that's when you change page ooh so in fact Mazal add it now so call it go to page application page chat because one thing we don't want to do explicitly everywhere will go into pages like we go to the chat page now we want to show the side menu but then if you go to the chat page in the register page you don't also want to then do current pages chat page and then side menu visible is true you don't want to do that twice so that's how a function called go to page let's change this to a private cetera so you can't just manually tell it to go to a page you have to use this function make this properly navigates to the specified page page page to go to and then in here we just set the current page equals page and now show side menu or not have page equals equals and for now chat that's the only one or in this case show that we call it side menu visible equals true only if the page is chat that's like a little helper and I think we do that somewhere else this is probably going to complain that we're trying to set a private value yet so now in the log in async instead of doing current pages log in change that to go to page login and that was one other place here go to page register it's no goal that will help the function go to page and then when we tell it to now go to the chat page the side menu should be visible so we should be able to click login well let's check there we didn't break anything first yep let's now we click login after one second this should slide out in the side menu should slide in and the chat page should slide in this way I think oh and that's nice it's that looks really cool in fact I just like the plain text they're having that's the finished application right there so we'll get in far now that's all done I'll probably style the side menu in a short little video just on you know scrollbar styling or something make a nice scroll bar in a video shortly so that's got us now the login and register page fully done and a little nice way to you see the application actually working now you can imagine you've logged in you click and everything starts loading in and we've got all this animation happening which is really adding to the you know the professionalism and keeping the app modern so I think next will style the scrollbar we will probably move this up to here so that the setting can go then we can collapse us out the way maybe make a collapsible menu that these icons go down there and shorten out and then we'll make finally make this main chat screen here which is going to be a huge amount of work but that will be coming up very shortly now so again hopefully this video was useful any comments anything you're not sure of anything you didn't understand do just post a comment and I always get back to everybody and I can even do video follow-ups to explain things in more detail again hopefully this was useful let me know what you think [Music]
Info
Channel: AngelSix
Views: 35,112
Rating: undefined out of 5
Keywords: wpf, animation, page, frame, navigation, data binding, view model, mvvm, storyboard, tutorial, example
Id: 0IE4osmIV0g
Channel Id: undefined
Length: 53min 3sec (3183 seconds)
Published: Sun Apr 23 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.