Welcome to MSDN Blogs Sign in | Join | Help

Displaying a graph using databinding and styles

This example shows how databinding and styles can be used for displaying a set of connected nodes. To better illustrate this, I've added some basic interactivity: the nodes can be dragged using the mouse and databinding will update automatically the positions of the lines.

For simplicity, I will use a set of predefined nodes and a set of predefined lines connecting those nodes (but, the functionality could be easily exteded to create them dynamically).

I've used mainly Microsoft Expression Interactive Designer for creating this sample, but because of some limitations in the current CTP, I had to tweak a few times the code manually. The project can be opened and edited by Microsoft Expression Interactive Designer without any problems.

This time I won't create a step by step tutorial; I will explain shortly each part of the code and how everything works. So feel free to download the project, open it and Visual Studio or Microsoft Expression Interactive Designer, run it and look through the code.

Canvas as the Document Root

We will use a Canvas as the DocumentRoot. Canvas is a simple layout container which allows positioning children by specifying X-Y coordinates.

By default, Microsoft Expression Interactive Designer creates the DocumentRoot a Grid. In order to create a new scene with a Canvas, you need to uncheck the option "New Scene Creates a Grid" from the "Tools" menu. The scenes created after that will have a Canvas as the DocumentRoot

Defining a Style for a node

Styles represent a great way to reuse properties and events. This is what our style does:

  • Sets the Stroke to black
  • Sets the Fill to red
  • Sets the Width and Height to 50
  • Sets a RenderTransform which translates to left and up with 25 px. This will cause the ellipse to be centered around its top-left position.
  • Defines event handlers for MouseUp and MouseDown
	<Canvas.Resources>
		<Style x:Key="NodeStyle" TargetType="{x:Type Ellipse}">
			<Setter Property="Stroke" Value="#FF000000" />
			<Setter Property="Fill" Value="sc#1, 1, 0, 0"/>
			<Setter Property="Width" Value="50" />
			<Setter Property="Height" Value="50"/>
			<Setter Property="RenderTransform">
				<Setter.Value>
					<TransformGroup>
						<TranslateTransform X="0" Y="0"/>
						<ScaleTransform ScaleX="1" ScaleY="1"/>
						<SkewTransform AngleX="0" AngleY="0"/>
						<RotateTransform Angle="0"/>
						<TranslateTransform X="0" Y="0"/>
						<TranslateTransform X="-25" Y="-25"/>
					</TransformGroup>
				</Setter.Value>
			</Setter>
			
			<EventSetter Event="MouseDown" Handler="OnMouseDown" />
			<EventSetter Event="MouseUp" Handler="OnMouseUp" />
		</Style>
	</Canvas.Resources>

Adding a few nodes

Now, when we create a new node, we just need to specify its style and its position, because all the other properties and the event handlers are defined inside the style.

	<Ellipse x:Name="Ellipse" Style="{DynamicResource NodeStyle}" Canvas.Left="448" Canvas.Top="133" />

You can also add new nodes using Microsoft Expression Interactive Designer:

  • Draw a new ellipse
  • Right click on it Edit Style - Apply Resource - NodeStyle; this will apply the existing style to the ellipse
  • Microsoft Expression Interactive Designer creates by default some attributes; the problem is that, in this case they override the values defined by the style; so we need to clear those attributes (in the Properties palette, click on the property and select "Clear/Default"):
    • Stroke
    • Fill
    • Width
    • Height

Defining the lines

We will define a set of predefined lines, and databind the coordinates of the two points to the coordinates of the nodes (the attached properties Canvas.Left and Canvas.Top). Unfortunately, the only way to do this step manually, because Microsoft Expression Interactive Designer has currently some limitations (we know about this issues and we hope that we will improve them in the next releases):

  • it doesn't allow to create a Line object.
  • it doesn't support databinding to an attached property.

A Line object has two pairs of values representing the coordinates for the two points: X1, Y1 and X2, Y2. Here is how we can bind one of the ends to the coordinates of one of the ellipses:

	<Line Stroke="#FF000000"
		X1="{Binding ElementName=Ellipse, Path=(Canvas.Left), Mode=Default}"
		Y1="{Binding ElementName=Ellipse, Path=(Canvas.Top), Mode=Default}" 
		X2="50" Y2="150" />

The logic for moving the nodes

First of all we will add an event handler for the MouseMove event of the DocumentRoot element. We will name it OnMouseMove. This step can be done using Microsoft Expression Interactive Designer by selecting the DocumentRoot and using the Events palette to add the event.

We also need to add the events handler OnMouseUp and OnMouseDown defined in the style. Unfortunately this step needs to be done manually at this point.

The logic is simple: when we get a MouseDown notification, we store in a private field the sender (the node) of that notification; in the MouseMove handler we will update the position of that node. This is the final code:

	public partial class Scene1
	{
		
		public Scene1()
		{
			// This assumes that you are navigating to this scene.
			// If you will normally instantiate it via code and display it
			// manually, you either have to call InitializeComponent by hand or
			// uncomment the following line.
			// this.InitializeComponent();

			// Insert code required on object creation below this point.
		}

		private FrameworkElement movingObject = null;

		private void OnMouseMove(object sender, System.Windows.Input.MouseEventArgs e)
		{
			if (this.movingObject != null)
			{
				Point mousePosition = Mouse.GetPosition(this.DocumentRoot);

				this.movingObject.SetValue(Canvas.LeftProperty, mousePosition.X);
				this.movingObject.SetValue(Canvas.TopProperty, mousePosition.Y);
			}
		}


		private void OnMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
		{
			this.movingObject = sender as FrameworkElement;
		}


		private void OnMouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
		{
			this.movingObject = null;
		}
	}

This implementation could be improved (for example, if you click on the edge of an ellipse and move the mouse just a little bit, you will notice that the ellipse will "jump" so that it will be centered on the mouse pointer.

Running the application

Once you've got all the code in place, you just need to build and run the application. You can click and move different nodes and the lines will just update automatically.

Notes:

  1. The attached project requires the Feb CTP of WinFX Runtime Components Feb CTP. The corresponding version of Microsoft Expression Interactive Designer is the March CTP (which should be released soon)
  2. This sample shows a very simplistic implementation for the drag-drop behavior. A better approach is presented by Unni in his article - "Panel Like" system.
Published Tuesday, March 07, 2006 12:15 AM by adrianvinca
Attachment(s): SimpleGraph.zip

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# re: Displaying a graph using databinding and styles

Wednesday, May 31, 2006 1:14 AM by brij
hi, i was trying to bind the Points property of a polyline, but i am not being able to can u plz explain hy.

your code is good enough

# re: Displaying a graph using databinding and styles

Wednesday, May 31, 2006 2:33 PM by adrianvinca
Hi,

The type of Points property is a more complicated structure (it is a PointCollection).

You can't databind individual Points (like I did in the Line example) because they are not DependencyObjects and you can't define bindings on them.

But you should be able to databind the Points property to another compatible property (e.g. a property which returns either a PointCollection or a string representing a PointCollection). (You could also databind to a property which returns a different type, but in that case you might have to write a ValueConverter.)

Basically you could expose a property in your code behind class, which would calculate those points and than databind the Points property of your Polyline to it.

Here is a simple example you could try: databind the Points property of a Polyline to the Text property of a TextBox. When you run your application, the polyline will get updated automatically based on the text you type in the text box:

<Polyline Stroke="#FF000000" Points="{Binding Path=Text, ElementName=TextBox1, Mode=OneWay}"/>
<TextBox x:Name="TextBox1" Width="200" Height="100" Text="448,133 143,283 535,325 294,114"/>

I will try to post an example in the future showing this.

Hope this helps!
- Adrian

# re: Displaying a graph using databinding and styles

Friday, June 02, 2006 1:47 AM by brij
Yup,
    it helped!!! thanks a lot.

My task actually is to create a graph control in WPF, do u also know some good resources over it.

Mission I M Possible :)

Thanks a lot again for the above explaination....


Happy Coding...



# re: Displaying a graph using databinding and styles

Friday, June 02, 2006 8:01 PM by adrianvinca
Hi again,

Regarding the WPF side of things, feel free to ask questions on the Microsoft discussion lists for WPF or Expression Interactive Designer.

This could be done in WPF in a few different ways:
- (easiest) inherit a class from Canvas, and extend it with the functionality for drawing graphs - adding lines, nodes at runtime, using code; expose properties for setting the graph data externally or use the existing DataSource/DataContext properties if possible.
- inherit from Control, in the xaml provide a template which has a canvas; implement the logic in code (very similar to the previous suggestion)
- (pretty complicated) try to customize an ItemsControl, by changing the ItemPanel to a Canvas; than create DataTemplates to generate the nodes and the connections based on the DataSource you provide. Basically this way, you would try to get the most of logic in Xaml.

On my opinion, the most challenging part in creating a good graph control is the layout engine. Of course, for the begining, you can use a simplistic approach (e.g. display the nodes on a circle, on predefined locations... or even randomly :))

I encountered once an interesting tool for generating the graph layout: http://www.graphviz.org/. I don't think it has any wpf support though.

Hope this helps!
Happy coding to you too... I am looking forward to seeing your graph control!

Regards,
- Adrian
--
This posting is provided "AS IS" with no warranties, and confers no rights.

# re: Displaying a graph using databinding and styles

Friday, August 11, 2006 1:35 AM by brij
Hi,
   My control is taking shape...Will share it for sure..when the client gets the delivery...

My graph has two controls...one is a low level graph rendering Canvas based control, and this control is later hosted in another control...to provide the Legends box and some other information..

# re: Displaying a graph using databinding and styles

Monday, August 14, 2006 5:39 AM by adrianvinca
Awesome! I am really happy to hear the good news!

Regards,
- Adrian
--
This posting is provided "AS IS" with no warranties, and confers no rights.

Leave a Comment

(required) 
required 
(required) 

  
Enter Code Here: Required
 
Page view tracker