 Welcome to the Network Engineering video blog. I am your host, Michael Crane. In today's video, we will be using WPF's routed events to bubble up the delete node and delete link commands from the child view to the main window. If you recall, the add router, switch, and test set commands, which are nodes, are executed by right-clicking on the main window canvas and selecting add from the drop-down menu. The main window then adds the view to its canvas, or the child to its canvas. However, to delete a node or link, the user right-clicks on it and selects delete. But the child must notify the main window so it can remove the child from its canvas. So we are going to add a couple of custom routed events to send the delete command to the main window so it can execute or handle the delete node and delete link events. We're also going to add a couple of index managers for the nodes and links so we don't have to use the index value returned from canvas.children.ed command because that had some problems. So let's get started. So let's see. Where to start? I guess we'll start with the class node. I'm actually on the main window. It's fine. Where is that guy? It's right here. We'll go to changes. There we go. That's better. So to bubble up that delete node command, I had to... I mean, there's probably a couple other ways to do it, but from the reading I did... Oh, and by the way, so the documentation I'm using is... Dave Fenton. This is an old post, 2012. But it's in C sharp in case you're wondering, but it's very similar to Visual Basic. Anyway, this is short and sweet to the point. It's a pretty good example. It doesn't work exactly like Visual Basic, an idea. And then, of course, I always reference Microsoft documents because they're supposed to be the one, you know, putting together this architecture. So Microsoft should be coming straight from the horse's mouth how to make this work, right? So I tried reading this routed events overview and I got about halfway through it before my eyes glazed over and I about passed out from boredom. Well, I can't say that I am an expert on routed events and, in fact, I'm probably not an expert at all, but I did get it to work. And the other documents I used were this handle a routed event. This is pretty good. Create a custom routed event I also used and this one was pretty good as well. And actually, if you compare this create a custom routed event with Steve Fenton's here, you can kind of, you know, use both of them to kind of whittle away what needed to be actually done. And I don't remember why. Now, this was pretty good. This actually works pretty good right out of the box. But I was kind of just cross-referencing it with what he had because for some reason I found this easier to read. Maybe he explained it better for me than I found this document. But they're both good. Is that the only one? Let me think here. Create a custom event, a handle routed event. And, you know, I kind of looked at this overview. I mean, I kind of looked at all of them really, but those are the three I mainly use. And if you're wondering where it's at, it's in the .NET framework, Windows presentation foundation advanced tab. So you just click on advanced. If you go up here and then just click on advanced and then it's under events. By the way, I also looked at this input. I found reading this input overview even more confusing than the events. The event I kind of understood. And this looks like it's event-based. In fact, from what I was reading, it's using the same engine as the event processor. And you can read through this. If anyone has any comments on which one would be better, because like I said, I just use a straight event and maybe input would have been better. Anyway, leave it down in the comments. It'd be interesting to get other people's opinion on this. That's about the documentation. Let's go see what I did. Okay, so I added an event. And here's the event right here. It's using the bubbling routing strategy. And you pretty much just add this event name. And then this is the custom event right here. And you can read in the documentation all this stuff as adding the handle or moving the handle and raising the event. And it's interesting in Steve Fitton's C-Sharp, they didn't have this, but this won't work without this. And then you come down here, and so on the delete node, when we right-click at the delete node event is handled by, let's move this over a little bit. Okay, so it gets the mouse button event. The sender is a list box. And basically right now it just doesn't do anything. It just basically writes a debug statement and actually writes a couple debug statements. It's looking at the XY position of the mouse. And then you have to define this new routed event args using your new delete node event, right? And you just say me.raiseevent new event args. Okay? To me it's not very intuitive. Thank God they have an example. Someone that is probably more familiar with these routed events might understand it better or if I actually read the documentation that would probably help too. But it does work. It's a little verbose for me or I would like something a little more trimmed down than, gosh, I know there's about 20 lines of code not including how to raise it. Thank goodness we only needed one, right? So anyway, so once you raise this event, by the way, if you don't know, a bubbling is going up the tree. So if you want to send a notification to the main window to the parent, you know, to the parent window, you bubble it up or you tunnel it down. So if you're going from the main window and you want to send a notification to the child that would be tunneling. All right, so let's go to the main window and let's go up right here. So I had to add a couple entries here in the xAML and it's just saying that to expect this event, this delete node event that's in class node, when it gets this event, it's going to execute delete underscore node, okay? And there's also a delete link in the link class, which we'll look at here in a second. Okay, and that's the only thing in this xAML. And if we go into the visual basic of the main window, there's quite a bit more. Let's see, it's not that. We'll look at that here in a second. Add link, there we go. Delete node. So it's going to fire off this delete node handler, I think is what Microsoft calls these things. I call them subroutines, but anyway, it's going to fire off this delete node handler. And these are just debug statements. I left them in there for people to look at because I found them handy to debug what I was looking at. I'll probably remove them later. So we're going to get the class node, that raise the event. I'm going to cast it. And if you look at the example, they cast it straight from the framework element, which is like, I don't know about. Yeah, it's an inherited element, right? So class node is inheriting. Oops, where are we at here? Anyway, it's inheriting user control and then user control, inherits content control, control, and then framework element. I was getting to after that rather lengthy explanation, because they were using this framework element to grab the name. And that actually would work. I could have used the cast, right? Let's see, where is it? I could have used framework element right here. But to me, it was easier to read just putting class node because then I knew exactly what it was looking at. But yeah, so this name right here is actually in the framework element. So when you set it in class node, you can retrieve it from the framework element. Hopefully that makes sense. Anyway, let's go ahead and start it. We'll look at it real quick. All right, so we're going to, if you watch the immediate window down here, we're going to add the router. And here's the... Oops. We added the router. I was looking for the debug. We added the router. So now when we delete the router, and now we can see the information that was bubbled up. So you can see main window, delete node called. The routed event was delete node. The owner is Mogwai class node. That's where the events defined. It says handled equals false. It hasn't done anything yet. And routing strategy is bubble. Okay, and so here's the node type as a router node. And here's the name router zero. This is all I needed. I mean, I may be in the future, I'll need this to know exactly what type of node is, but just knowing it's a node, all our nodes are in one collection, so it's easy to delete them. Or it's easy to find them, I should say. Okay, so before I delete the node, now that I know which one I'm deleting, which is the ID or name, actually router underscore zero, I can... All I want to do is delete all the dependent links associated with it. I didn't actually test this, but I didn't want any null pointers for those links pointing to a node that'd been deleted. So I figured it'd just be just some good house cleaning to delete the links first and then delete all the dependencies, I guess, on the nodes and then delete the node. Okay, so that's what I'm doing here. I'm just going for each link in the collection of links. If our router underscore zero is either node A or node B, then delete it. And then after that's done, after all the links are deleted, you just remove the name, and we can look at that real quick. I mean, after I delete all the links, then we can remove the node. All right, so we remove it from the collection of nodes and then we remove it from the main canvas. All right, and we'll look at that real quick. So if you haven't had router, let's see. All right, then we add link. Okay, so if I want to delete router zero here, then what's going to happen is it's going to delete these two links first and then delete the node, right? And that's what it does. Okay, so the last thing in here that I added was this setting the handled for the event to true. And since this main window is root in the tree or the final stopping point, I can't bubble up any further in other words. This is probably not needed, but from what I read, it's a good practice. So the delete link is actually an overloaded subroutine. One takes the event. Instead of adding this to the delete node routine and the delete link routine, I just made it its own overloaded subroutine. Okay, so here's the delete link. Well, we can go ahead and look at this. It's basically the same thing. I was going to go look at the event first, but it doesn't matter. Let's look at this. This is in the main window. So this is the event's going to send. So sender is object. What's going to bubble up? It's going to fire off delete link. And it's exactly basically the same thing as this delete node, except we cast it into a link. And we're deleting the link. And then I just call this delete link. All right. And then we do a handle equals true. And we can look at that real quick. Let's see here. So you add link from router one to router two. And now, so just right click on it and delete. And there it is. So you can see the main window event delete link called. It's a delete link is the name of the routed event. It's in the link class, which I'm probably going to rename this. I don't know. I was thinking about renaming class node to base node, but I don't know. And renaming a link to class link or base link or something like that. And I'm not going to do that this time around. But anyway, so he's in the class link and handled false and routing strategy as bubble. And this is his name. Right. And really, this is all I need. I don't need any of this other stuff up here. I just added it in there for debug when I was looking at it and left it in here so I could show it to you in the video. Right. So if we go to the link class here and see where are we. So here's the event. And like I said, I'm not going to try to explain how all this right here works. You can go read about it. I am not qualified to explain how all this works. I just followed the example and it seems to work. Okay. Like I said, it's a little bit verbose for my taste, but it seems to work. There's probably better ways of doing it. And if other people know a better way, let me know. So anyway, here's the there's event name and here's the custom event. Yeah. So this is registering the delete link event. And this is defining that the link or adding the handle how it handles it. I don't know. You'll have to go read the documentation. It seems a little redundant to me, but you know, who knows? It probably makes sense to a lot of people. And that's about it. It's this exact same thing as the node class node. This is just going to create a new event args or new routed event args called event args is going to be using the delink link event that we defined at the top. And then it's just going to raise it. Okay. So another thing I changed is also in this main window XAML. And that is I changed how we use the index values. So previously, and I kind of left it up here. It's commented out. And yeah. So before we used to get our index value when from the return of adding a child to the main canvas. And yes, the index is unique on the canvas. But the problem I was having is when after I got delete working, I was doing some testing and when I would delete a router, these index numbers were getting re-indexed. So in other words, if I deleted node zero, it would re-index a whole collection where it was storing all these index values and renumber them all. And since I was using the index value in my name identifier, because I needed a unique name, it was causing duplicate values. So I had to scrap using the index value of this childchildren.add return value, right? So now I just add the router to the canvas and I created a new subroutine called get available node index and get available link index. And they're both right here is get available link, get available node. And yeah, I know a lot of this code is duplicated. And it probably could be cleaned up and I could probably pass some objects around in here and maybe the collections themselves. I don't know. Anyway, I didn't want to mess around with it. They're pretty short. So we'll just look at one. They're identical. Well, pretty much it's, you know, so I start with just a 4-2 loop. I guess it's not really a loop, but it's a 4-2 statement where we go. We just iterate the index numbers from zero to max nodes. And I define maxlobes, max nodes and max links in these, in this mod globals up here. And I just, I just randomly picked a thousand and four thousand. For max, I don't know why I picked those numbers. They just seem nice and big. So anyway, it's going to count from zero to max number. It's just going to look in each collection, collection of nodes and collection of links and check to see if there's an index value. If there, if it finds an index value that it's going to use. So it's going to start counting from one to a thousand. It's going to check, is that index value in there and if not, keep going. And then when it finds, or doesn't find one or finds an available one, it's just going to return that value and then we're going to use it in the name. And that's it. And I guess we can look at that real quick if you want. It's not terribly interesting, but it basically does exactly the same as what it did before, except before we didn't have the delete. So we didn't see this problem pop up. But okay, so I added three routers and then if I just delete one router and I say add, you notice that it finds index one again. It doesn't like say index three because otherwise, you know, after a lot of adding, deleting of something, if I just kept going up the index value, you would run out of numbers. So we reuse index values when we delete them. Okay. And so I just added this get available index to all the different add commands and also the get available index for the link command. That, I think, is it. Let's see if we looked at ModGlobals. Let's see if we looked at this. That's it. Don't forget, you can support the Network Engineering video blog by donation using a credit card and PayPal or by purchasing products at the Muxall store. Details and links are in the description under this video. Well, that's it for this video. If you like the video, give it a big thumbs up. That helps and hit the subscribe button. That really helps. If you have any questions or comments, post them in the comments under this video. Thanks for watching and I'll see you next time.