C# WPF UI Tutorials: 30 - Sending a Picture Message

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] so carrying on with the peseta word application this time we are going to add we've done sending messages now we can send the message we're going to add the ability to at least view picture messages and then eventually we can do the you know a touch from computer and show a picture message and show all the files but we'll start with the basics of at least displaying a picture message and binding that to view models so in order to do that we'll obviously need to adjust this view model that's bound to the the chap message item so that would be the chat message let's start from view model and then here we'll need to add another item really for attachment or you know specifically say image and then we can tweak we can either do one thing and that's to have an attachment for an image an attachment for a file an attachment for you know specifics that we understand which is then what we're going to do or you could just have a generic attachment that kind of gives you you know the the file size the file name the file type you know and then handle it that way but to start with I think we're gonna have more of a basis of as we get the data from the server we all figure out what type of file it is and we can have handles to handle those specific pieces of information like if you send a link to a website we want to then display a mini picture of the website so we're gonna have a few model for each type of attachment and so let's start with creating a new file for that so if we go to the view models minimize all this lot and then we got the chat message list item view model it's just copy and paste that changes to chat message list item image attachment view model so nice big name a view model for each chap thread item items attachment in this case and image in the chat thread so that's that then in here we can clear all this off I will start with will probably end up with also a base attachment but for now again let's just start with what we have so we know an image polygons a title so the tile is gonna be different than the image name you know the file name there we might allow them to send a picture and give it a you know a specific title so almost like a name without changing the actual file name so at the point of that they won't have the file size and part will also have as we just mentioned the actual file name so that will be the original file name of the just a attachment the file size in bytes of this attachment we have file in file size will want we can have file Thai all can just have say extension so it depends I want to handle this we've got an extension in file name but in terms of them binding we could have that or in fact we'll leave that for now until we need something you know like we might handle pngs or JPEGs differently so we can always add it later but let's just leave it like that for now then we have we'll have a public string for the thumbnail ill and remember this is coming from the web server when we make the web server so for now we don't have a web server we're just going to we know we need one though so we're gonna first make a region here if I can remember how you do that shortcut before telling me there we go region then double tab and it automatically makes a region private members and then this will be private string and from a lil that will do for that just want to check about actually do so I'm just gonna check the comments and they usually do for private they usually do the full one okay the thumbnail of this attachment so the thumbnail we will return the thumbnail fine then inset we will have so that if the value is the same form then we don't do anything then if we do have a value we want to update the value so update the vacuum field here and then here this is well put it to do that because the problem with not having the serviette and not getting a lot of stuff that I wanted to do in this application we need to start separating core out and adding more things like a web manager so we can download things and we can query the API when the websites off all that kind of stuff isn't done yet but everybody's after you know these videos on WPF so I'm trying to build the website and slowly start building the additional backing code in other videos but also try and maintain doing some UI videos at the same time so for now because we don't have the download manager we'll simply put it to do and state what we have to do so this would be originally to download an image from website you know from wherever we gained from we got our nails were basically a link to a picture on our service website eventually and then we will also create a thumbnail the male sized version because you'd have you download the whole either this would be an actual thumbnail of the file which is the ideal in fact it would be so we wouldn't create a thumbnail the server would serve a thumbnail and then when they click we could also ask for the full-sized version so we download the thumbnail and then we would save file to local storage and cache so we don't have to download it every time we look at the picture and then we would set local file path value but we don't have yet which is going to be public string local file path this is the this path here so once you've downloaded the file and you've saved it to you know the local storage on this hard drive in the applications cache folder which we've got to build then we would set this local file path and this is the ultimately what will bind the image in sam'l 2 so this would be the actual literally a path on this machine to simply display an image which would come from setting the thumbnail oil so you'll see you come together as we go on with this video so this is the local file path on this machine do the downloaded for male so we would set the value to that and so then for now you just leave em each directly directly so this is just gonna simulate your set and oil will pretend with download date and then typically we would set the local file path to wherever the result of the downloaded image come from but right now we're just gonna put a dummy we'll do our sample rusty picture that we already have in our application which we have in images samples rusty so for now any picture we specify a thumbnail tool will always be this image but it's good enough to get the UI done and you know that he is effectively where you tweak you'd do this if you wanted to do it in advance of me doing it so that's the I think everything we need for the view model there I want to rename the class or the file rename file there we go and then to now make use of this we first need to have one of these items so we need to have it in chat message just item so it's in here so we would have public big long name image attachment and the other thing I'll mention here is that with doing the photo previously in doing all the chat applications I will now strongly strongly recommend the single unit a single message coming from the server or being sent always only ever contains one attachment so you might want to attach a website mountain or touch my websites about example that's just a string in the message but you might want to attach a PDF amount to attach a file or a video or an image or anything else in the current for settle application the one that's live on the store we allow multiple attachments in one message and the issue that leads to is one maintaining the cache the state the restoration and the clearing up of file that could have nine out of ten files uploaded and then gets canceled or deleted or crashed or anything else then you've got nine files left in memory and left on a server in the middle of nowhere you've also got them handling viewing multiple files and doing a UI to then show you multiple files you have to do the UI for them deleting and managing attachments before you send them there's so many additional requirements wouldn't you start simply attaching multiple things per message and you also lose a lot of the benefit of being able to then directly comment on say this single attachment all of this message has only ever got one attachment and you wanted to comment effectively on this image you simply comment on the message so then the system that allows you to comment on a message that we'll do in future would be the same you wouldn't have to do extra work so simply from hindsight and the fact that I've done this many times before I would not recommend doing multiple attachments if you want to send ten picture messages that's fine we simply build the client to upload one picture send it as a message upload the next senators message and process it in that way don't talk load a bunch of messages then attach them to it don't bunch of images attach them to a message and send a single message that's not really ideal at all so with that said we've now got an image attachment here a single one and we'll couchette if we then attach PDFs we'll have probably another view model like this that says PDF attachment specific ones that we want to handle differently that is and then we'd have a generic file attachment for everything else that we simply show with you know attachment download file name file size type of thing but the reason we want specific attachments here as I mentioned is so we can we can actually make a visual display differently so the attach of video we can make a video attached model that could actually play the video live inside of another message and to do that is much cleaner to simply have multiple attachments so again all this will come clear it as we go forward but that's just a little background as why I'm doing this if you're wondering why I'm not just saying you know attachment and it can handle all attachments it can but will have a file attachment for that and this is then special cases form we want to handle them differently like DM each way we want to display a full-size picture and so this is the attachment to the message they type into the message or rather the image attachment or now it's open to the message as it is of an image tab and we now have the image attachment and want a few helper properties so we will want for the UI side of things and we want a boolean because now what we want to do is say we send a picture message you know we attach this but we said no text we simply want to send a picture we don't want the bubble underneath with the text to show a blank bubble so we will do a has message one first that is simply message isn't it that's all check like indicating every have message or not and what's you complaining about oh yeah I'm thinking I'm leaving data no in fact you know it is I guess if I just I don't need to get set it's not suitable there we go so that will simply display true if we've got a message false if not I'll have any message text then we'll do the same for image and then we do the same eventually for standard file attachments afterwards so we do have has image attachment let's say and this is EV image attachment isn't equal to null all right so what the house message has a mean attachment I've got the image itself so I think that's all we need for the UI so we can always come back to this if not so there are the three things we've added to the view model at the moment and now I think we should be good to go to list item view model and when we open it let's at least add some picture message so the bottom one you know this is a bit of a new line issue there it's all copy and paste this bottom on again well in fact we'll just change this bottom one so I'll start with a message and a picture so we'll do the message that and then we'll simply do image attachment is new view model you'll see we don't come up far in file size anything for now we just simply want the thumbnail l equals HTTP anywhere weather doesn't matter so this would be the you know the thumbnail this will obviously come from the server like we're typing here this would be specifically pulled them from the server and it would be an oil to an actual image but if it doesn't matter for our case because we're simply bypassing that as we mentioned here and just setting by default so we've now got a chat message with an image attachment and we expect this to show now in the UI so that's where we need to start going so we've got the chat message list out and control and we are going to start with we want the way I'm seeing it is you can attach a picture you can also have a message as well so you want them picture to appear both in its own little bulb so we need to separate this UI a little bit first let's try and figure out where we are with this we've got speech bubble rectangle chat bubble anchor and time container so the time at the bottom wants to stay where it is the chat bubble anchor and the speech bubble rectangle those two things are really specific to this chapel so we want to keep them together but we need to now have because we are in a grid here the main container we will need to I suggest this so we know this is going let's just remove this for now but cut it so control X to keep it in memory but that's gone we are now need two rows not three because we have the tank container and then all the content so we'll have a new container just a grid for now that is now going to contain all the new stuff that will want to rose again let's just paste this back in now first and we'll cut it again just so I can move clone this here so this is now the message message text attachments red with two rows because right now we have an image and when I'm this original so we recut this now I've already done that border all the patterns going on here so it's that one again so we have two grids we will want another grid for Jeff message tapped bubble that's what we originally had I can now finally go in there so all the donors move things around here we've moved effectively this speech bubble an anchor with moved from outside this top grid into a main container grid and into a sub grid and this bridge wants to be on Row one because we want this text to appear below below the image just wondering why that and because the speed it's up there now because this is got grid row oh so this grid also needs a rail because this originally had a row so all of them I've got two rows at the minute there we go so that's now moved in that's all the same and nothing's changed so that should be good to simply minimize at the minute so we take a look what we had that hasn't changed us so we've removed one of the rows from the top red because now we've got a so instead of it having you know this Bob all this anchor in this text it's now just got the whole contents and then the time so remove the rail created in your master grid there's kind of two rows one for an image one for this text bubble and then inside we've specified the second grid already just for the tax bubble which then has the two rows again as it did before and dump them in so it shifted all that around and now we should be left with an area here to now do our image bubble this will be immediate action and then I won't know one thing we wanted to do is this whole row for the catch bubble we wanted to set the visibility to the has message and the converter needs to be now will lead a new converter because that's boolean to visibility converter does hidden and we don't want to hide the bubble we want to make it completely collapsed invisible so if we just quickly make another value converter boolean to visibility copy and paste that and one thing I will do in the next video is we really need to reach invert these values right now by default if we specify true it's hidden and false the other way around sounds really annoying so for this new one we'll fix it and then we'll go back and fix the Leola so boolean to visibility Dom convertible calling this new file copy and paste it there first it takes in a building with invisibility where false is visibility dot collapsed rename the file flip these around so I've got this one pasted this one the fact I'll showing you short but to keep forgetting to use your simply on the lining you'll hold the Alt key and now press down you can move the the lines around that way as well and instead of cutting and pasting so we have we've inverted the logic so now it's true it will be visible and if it's false we want to now change it to collapse so that's all we need for that new value converter so then this can now be that one and the whole chat bubble now will only be visible if we have a message otherwise it'll be invisible that's good now let's move on to displaying an image in this grid so I think for that we will need a border we know we want the corner radius ten inside the border we'll simply want the image itself and we'll won't now the image is inside the Oval the path to the images inside the actual image view model so we will pass in the image as the data context and then we'll then hunt the source of the image being the local local file path I believed and I think that we'll be able only to convert it to a know it that'll be a path so don't need any convertor we don't know nothing that's all we need to display an image so I think if we run that I think it'll actually should work in some fashion we'll need some clean up and tidy up but I think I should be click maybe not okay image ok let's try let's remove the binding initially bound on it's not gold image called image attachment doesn't it there we go there we are oh well that's a big picture of rusty okay so we'll get in there we've got a bubble we want some padding here first between the two that's a bit too much of a you know it's obviously butt up against there some text so we want to add some margin to the bottom some bottom margin let's just quickly recheck that and now we've got the padding we're also a bit large when you don't like to continue to expand them indefinitely so it's good that it resizes you know some resizing weather support I think we want but let me Tom that size so there's never too large so let's just simply put a much width on this of 600 and so I was like so that the image can never go you know just keep growing too crazy sighs that's better so that's a nice big picture and you know that's its limit you can even change that to whatever you're a graphing nutter a big enough picture otherwise you start getting distracted with all the you know that the huge image especially there's multiple we've now got an issue with this isn't rounding the corners and this is a it is often done in multiple different ways and typically the way you do it is draw a region or draw like a you know a path and then as a brush should fill that region in and I don't really like that that's always like a bit of a hawkish workaround and the problem is that because border gives us this ability to do rounded corners and we get so used to it and it's so nice we expect to simply put a rounded border on the border and everything inside clips inside of it and that's that's not what happens so instead of doing like oh well we want this image now to specifically be clipped and then we have to do you know specific code just to draw an image but then the next time you want it to be a video clip you'd have two totally different code again instead let's make a an attachment for any item inside of a border that can then effectively create a region through an attached property that matches its corner radius so what we'll do is have an attached property on the image that will set because in order to clip the image you can do image clip and then you can make a rectangle geometry and then you can specify I think you specify to me the values wherever you do but you basically create a you know a clicking region there so that's all we're gonna do but with an attached property that will match the corner radius here and create you know the correct rounded corners so let's go to attach properties copy and paste anything and do border attached properties and then in here we will call this clip from border property which basically means you know create a clipping from the parent border so we'll say creates a clipping region on the parent border corner radius then on value changed its first white ball that's kind of the same you have to first get itself which would just call self and send it is just gonna be anything we're gonna work with anything here so framework element and we know that work that's fine now get parent border so first if but Jack we have a parent order and if we don't we'll simply return so if not stopped up parent as is border for the variable called border then we'll return but we'll also just think well we're testing this or you can stay in anyway I'll just did you buggered up break so instead of just blatantly ignoring the fact and wondering what's going on if it fails we'll it'll stop the debugger at this point for us to make us realize we've done something wrong then if we do have the the parent border we want to first see if the value is true if true look into events so if boolean you got new values of the specified true or look into events otherwise on hook so the events we want would be when the border first loads because we want to get the what we want to do when it loads well in fact it's gonna be the same thing both times when it's loaded will be the first time we have an actual width so it's been rendered at this point then we can draw the clipping area but then as well as once it's loaded every time it changes size we need to redo mmm delete that use the same one so every time you change your size you need to redo the clip you know because the clipping region you've specified is the exact rectangle it's not like a adjustable thing like in a grid where things resize you have to redo the clipping area every time so we have to do every time it loads or rather the first time it loads because it only happens once and then every time the size changes so if they change the value to false we'll remove the event handlers and we will also probably own a WPF video but in a general c-sharp video will also talk about event handlers and on hooking and things because I'm sure we'll have some memory leaks in this application now that we should start to debug mainly around almost definitely around things like attaching properties and attaching events and never on hooking and lifecycle changes so that's for another video though and it won't harm us for now so when we set the value to true which we will do will hook into these two events and then in the was it created two events oh no we don't need that I can do it that one the both handleable by just a rigid event all the form the order is loaded and change sides so now every time the border changes first we want to make sure the sender is a border I'm not really really need to do that because we know it's always s because we've attached it here so in fact no number there doing that let's just say for our border equals order Center we know it's always s then we want them to figure out the child which should only ever be this property and can really only ever be it because we attach this property and the parent is not a border we return so if we carry on we are the child of this border and we hook into the events so the only time really this could this could be wrong here where we're going to get the child like this which is effectively it should be ORS is if the child has been changed and we haven't handled on hooking which is a possibility and it would happen but for now again we'll come back to clean up this the only other way we could do this is again with kind of a lossy we could place this event handler code directly in here but then on who Keenan who kena wouldn't be the same value in fact I know a way around this we will want to that's a good way I want to do a private routine event handler and this would be the M border size changed event handler and then in here remember that vigilant and the Sachi and okay so can we not do instead then a think of this would be maybe a delegate of an action of object and we did event aaaghh maybe not an event delegate action and will that work no okay save me messing around trying to figure out multiple different syntaxes the syntax here too to do this in line in fact let me just try see that'll give me the hint or what I'm after what I'm creating here so I've done this before we've done this on the unhooker ball event somewhere unloaded equal so what did we do with this oh yeah rooted event handle so we did the same thing but the problem is then we don't get the benefits of doing it both the same so yeah we're gonna have to now create two event handlers which is it's okay it's it's not at the end of the world was him to make a helper function so you'll see why I'm doing this in a minute I'll explain so let me just hammer this out and forwarder and size change the event handler so this will be private members so we've got actual properties here now and then we we will hook and unhook from those and then on the size changes do the same now the difference is we will have now a private helper function order and just call it boarder unchanged and then in here now so we'll stay inside this on value change so we have access to it ourselves well then say I'm border loaded equals estarĂ¡n yuan and this will call border unchanged and so on settle loaded event and then setup size changed to do the same thing so now we initialize the two variables here instead of having it in this function because what happens here is in this function and in fact we will pass self so the issue we had before in fact we don't even need any of those even if this we're not doing anything with them why should we open it with s1 to leave them in so if we did just the standard rooted event handle and size changed in here with the border we couldn't get ourselves guaranteeing that you know self is this exact item because as mentioned if we attach to the border then we hooked in to the event here and then the child changes on the board a Worstell hooked into the event so then when the size changes it tries to get the child presuming it soars and it's now a new child and then starts doing things so the issue becomes when we wanted to get ourselves so instead of just simply hooking into it a method that's outside we do an internal method here so we set them up internally so that we can not pass ourselves so this will be a framework element child need child on ourselves border so now the child we have so can get rid of that childhood passed in that's all good so I've changed it's never assigned to okay it's assigned to right there that's weird okay let's ignore likes it as assigned I think it's just a bit confused there that's just took I think as a compile time [Music] yeah it's a bit strange just you do that and then fail so it's definitely assigned to so that should go away when we built that back to over so now anytime the border is loaded all the size changes what we want to do is get the border which you've now gone get ourselves which we've now passed in as a child and we first need to check because this is going to be fired both on loaded and sighs changed and things like size change might be called before loaded when it's figured out its sizes but it's never rendered yet so it's reading all the time so we'll know when it's fully loaded and we can effectively do something with it once we have an actual size so we just will do Jeff we have an actual size and that's a simple case of we will do a border actual width equals zero and border actual height equals zero so both of those are zero then there's nothing we can do because we don't have a size to work with if we have a size to work with then we can set up set up the new child flipping area so onto rectangle as you mentioned before which a new rectangle geometry geometry in fact we can undo side like that and the radius x equals can we do radius no okay we're going do that because we want to set the radius x on y to be the same so wrapped up radius x equals four X dot radius Y so set they're effectively the corners of the rectangle which is what we're trying to do we'll get there into the corner radius matching the same that will need to be the we don't want a negative value so let's just make sure mathematically the zero so it never goes below zero or it'll be the border dr. Korner radius and the corner radius is or has okay top left bottom right so pick the top left and I think that will be Oh precisely you can have corner radius is all around so the only limit here is that we can't a corner radius goes up different sized corners so we're just gonna simply have to pick one of them so we're gonna presume the top left corner is the one with a clone so this will only work with corner radiuses that were the same all around which is pretty much all the time we never do a weird radius different on any corner so that will work but we've also got to factor in the the radius has got to take into account half of the border thickness because if you have a corner radius of ten then you have a border thickness you've got to account for that border around it and fatally hard for me to get to the center line to give us where the curve should be so if you have a really fat 50 pixel wide corner a border then the corner radius is gonna sit halfway between the outer edge and the inner edge of that line have that makes sense so we simply have to account for taking off half of the border thickness and again we'll just take say the left-hand side Kanzi 0.5 to give us half so all that's doing is setting up a rectangle with a corner radius that matches the ball just called a radius that's all it does that's the corner radius with the borders for radius and then we now need to set the actual rectangle size with a set rectangle size to match child's a full-size and this is where I'm saying you have to this is why I have to readjust all the time because the rectangle is the clipping area specific to an exact size it's not a flexible value so for that we need to set the rectangle of the rectangle over again and that makes sense so that would be a new rectangle that's a simple case of child render size and then we assign that finally to the child so sine lifting the area to the child to child dot clip equals the rectangle and that's all there is to it so what happens here is basically we attach this to now we attach this to anything that's inside a border which can only be one thing you know at a time this will then come in hook into the loaded and changed events once you finally gets a width and anytime you change your size we will then remake a rectangle that's got the same width and height as the child but with a corner radius of the what the board has got so I'll create a constant clipping that mimics the border hopefully so let's apply this to our image here let's do local : clipping border property equals true and let's run that and see if we get the clipping area there we go now we have a rounded region around and then one resize it should yeah their readers the clipping area so that's now a image coming in the only other thing here I'd say is this is not this is not how an image is loaded because you'd have to download it from the internet you know it to once you get a thumbnail ill you'd have to then go and fetch the thumbnail so we will have where do we set it out touch with and remote property not that but where did we I'm forgetting warm afternoon what was I looking for oh where we set the oil is in the actual thumbnail so at least let's simulate some kind of delay that we're downloading because this would take time so let's just add a task dark delay of say two seconds and then once it's done and if you're wondering what I know using the background as it's my dog snoring in case you can hear that on the mic so after two seconds we will set the thumbnail path and then this will give us more of a representation of you know the message load and the picture comes in so there we go and that's not as I mean that works but that's not ideal he just like jumps and appears at you so I think what we'll do I'll split this video ox I know people like shorter videos when we've we've had like a good milestone here where we're actually displaying pictures in the next video we will animate this in will create some kind of loading you know circle here that lets them know there's a picture loading and then it pops in when there is a picture and it will also fade the image in whenever he changes so it's a bit smoother than you know just banging in your face but I think that's a good enough stopping point I think we've reached a point there where we can now display picture messages and animating the picture masse Jen and displayed a you know a loading scene is kind of a separate video on showing you how to do that so I'll stop this video here and the next video the very next one I'll do will be you know how to animate this in so hopefully this was useful in showing you how to now get pictures into your chat messages again any comments anything you want to see you next anything like that just let me know and I'll get back to you [Music]
Info
Channel: AngelSix
Views: 8,798
Rating: undefined out of 5
Keywords: wpf, send, chat message, picture, photo, bubble, chat app, chat, network, real-world, cross-control, syncing, navigate, navigating, page, change, advanced, settings page, text edit, edit text, textbox, control, settings, slide up, dialog box, custom, ui, style, view model, tutorial, mvvm, binding, popup
Id: Bo_cxUjBa1Y
Channel Id: undefined
Length: 49min 28sec (2968 seconds)
Published: Fri Sep 15 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.