Categories: .Net, C#, MCA, Silverlight, WPF Posted by mheydt on 10/7/2008 2:21 AM | Comments (0)
Over the last few days I've added the capability to specify a different UI element for the nodes of the graph.  This picture shows the use of circles for the nodes.  Yeah, not too fancy, but its important moving forward.  I also added the ability to drag the nodes; that's actually a lot for fun.



One of the things that I did do when working in the drag functionality is to enable the framework to do the dragging.  I wanted this so that the programmer of the node need not worry about intercepting mouse events and handling the repositioning.

This was actually an interesting challenge.  Since the nodes can be of arbitrary shapes (rectangles, ellipses, polypolygons, ...), the framework can not know what the shape is and hence how to determine if the mouse is down in the visual element.

But wait...

What I did and something that Silverlight / WPF supports quite nicely, is that when the framework calls back into the client code to request creation of a node, the node can support a particular interface, and the framework will check for that interface on the node.  If it not supported, you do not get automatic drag.  If it is supported, it supports a single method that the framework will call that returns a UIElement to the framework that the framework will bind the mouse events to call into the framework.

This is interested for a few reasons.  First, take the sample shown above.  The XAML for the node is the following:



This is fairly straightforward XAML.  There are three elipses, the first two which form the teal background and white edge, and the third, which is named dragElement, that is for all intense purposes transparent and overlies the other two ellipses.

When the framework requests the UIElement to bind the mouse events to, this codebehind on this xaml returns the ellipse named drag element.  That element is then used to do dragging of the whole control.

There is a few subtle reasons why things are needed to be done this way.  For example, if you trapped the mouse events on the top level UserControl, mouse events outside of the ellipse but within the rectangle will also cause dragging.  Not good.

If you make it the white edge ellipse, then mouse events are only handled when the mouse is ac actually over the stroke, not inside the ellipse.  I found that interesting.

If you make it the Teal ellipse, then the border ellipse, being on top, prevents mouse events from going through when over the border of that ellipse.

Note: I realize I could use just one ellipse with a teal fill, and a white border.  However, if you notice, the opacity on the elements are different.  I wanted the teal to be slightly transparent, but I want the border to be totally opaque.

So, what I did is create the third ellipse, make it transparent, and to cover the exact size of the other ellipses.  This provides the drag capability I want, all with just supporting an interface and coding one method.

Note: I may change this model in the future.  This works well, but there may be better ways.  One way would be to create a property that can have an attribute that the framework looks for.  That might be better as it won't clutter the class definition with interfaces.  I don't know, I'm kind of 50/50 on that for now.n  If you've got an alternative way, let me know.

This model also will play nicely with irregular shapes as the UIElement returned could be a polygon, and all things should work the same.

Note: There are a few interesting things about the way this is programmed that I want to document in the future.  A lot of times in OOP to create a new control that would use different visual element, you might subclass the control and override virtual methods.  In this model, the framework uses events to request data from anyone that may be a client of the control.  I find this a lot cleaner as you get a better separation of concerns.  I'll elaborate on this more in another post. It's late now and I have a busy day tomorrow.

I'm also going to try and post a live version of this control during the week.

Comments