WPF Diagrams: Styling a Node Element
Tagged as WPF DiagrammingOne of the most powerful and useful features of WPF Diagrams is the ability to style any part of a diagram any way you want it to look and feel. One of the most common parts of a diagram that you’ll likely want to style are the node elements. When it comes to customizing the look of a node element there are 2 main things to think of first. First there is the style to be applied to the nodes, and secondly the data template that each node type should have. The data template is what seperates the look of one type of node to some other type of node. The style of all the nodes is generally the same, this is what provides a node with its MoveThumb, Resizer, and ConnectionPointThumbs. In this post we look at how to provide your own node style in your applications.
The standard DiagramNodeElement style uses a simple black colored Resizer, and blue gradient filled connection points as seen in below.

The best place to start is by copying the standard DiagramNodeElement style. Below I have provided the style used in the WPF Flow Diagrams product.
<Style x:Key="NodeStyle" TargetType="{x:Type ms:DiagramNodeElement}"> <Setter Property="FocusVisualStyle" Value="{x:Null}" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ms:DiagramNodeElement"> <Grid Canvas.Left="{TemplateBinding Left}" Canvas.Top="{TemplateBinding Top}"> <ms:MoveThumb Element="{Binding RelativeSource={RelativeSource TemplatedParent}}" Focusable="True" Clip="{TemplateBinding Geometry}" Style="{StaticResource {x:Static ms:MoveThumb.InvisibleStyleKey}}" Cursor="SizeAll" Name="Mover" /> <ms:Resizer Element="{Binding RelativeSource={RelativeSource TemplatedParent}}" Name="Resizer" /> <ContentPresenter Name="ContentPresenter" /> <ms:ConnectionPointThumb ConnectionPoint="{Binding Content.DefaultConnectionPoint, RelativeSource={RelativeSource TemplatedParent}}" Width="{Binding ActualWidth, RelativeSource={RelativeSource TemplatedParent}}" Height="{Binding ActualHeight, RelativeSource={RelativeSource TemplatedParent}}" IsHitTestVisible="False" Focusable="True" Visibility="Collapsed" Name="Connector" Style="{StaticResource {x:Static ms:MoveThumb.InvisibleStyleKey}}" /> <ItemsControl ItemsSource="{Binding Content.ConnectionPoints, RelativeSource={RelativeSource TemplatedParent}}" ItemTemplate="{StaticResource ConnectionPointTemplate}" Name="Connectors" Visibility="{TemplateBinding ShowConnectionPoints, Converter={StaticResource bvc}}"> <ItemsControl.RenderTransform> <TranslateTransform X="{Binding (Canvas.Left), RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource Negative}}" Y="{Binding (Canvas.Top), RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource Negative}}" /> </ItemsControl.RenderTransform> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <Canvas /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemContainerStyle> <Style> <Setter Property="Canvas.Left"> <Setter.Value> <MultiBinding Converter="{StaticResource CPX}"> <Binding /> <Binding Path="Formatter.Layout" RelativeSource="{RelativeSource AncestorType={x:Type ms:DiagramSurface}}" /> <Binding Path="Position" /> </MultiBinding> </Setter.Value> </Setter> <Setter Property="Canvas.Top"> <Setter.Value> <MultiBinding Converter="{StaticResource CPY}"> <Binding /> <Binding Path="Formatter.Layout" RelativeSource="{RelativeSource AncestorType={x:Type ms:DiagramSurface}}" /> <Binding Path="Position" /> </MultiBinding> </Setter.Value> </Setter> </Style> </ItemsControl.ItemContainerStyle> </ItemsControl> </Grid> <ControlTemplate.Triggers> <Trigger Property="IsSelected" Value="False"> <Setter TargetName="Resizer" Property="Visibility" Value="Collapsed" /> </Trigger> <Trigger Property="IsResizable" Value="False"> <Setter TargetName="Resizer" Property="Visibility" Value="Collapsed" /> </Trigger> <DataTrigger Binding="{Binding IsReadOnly, RelativeSource={RelativeSource AncestorType={x:Type ms:DiagramSurface}}}" Value="True"> <Setter TargetName="Resizer" Property="Visibility" Value="Collapsed" /> <Setter TargetName="Mover" Property="Visibility" Value="Collapsed" /> <Setter TargetName="Connector" Property="Visibility" Value="Collapsed" /> <Setter TargetName="Connectors" Property="Visibility" Value="Collapsed" /> </DataTrigger> <DataTrigger Binding="{Binding CanModifyConnectivity, RelativeSource={RelativeSource AncestorType={x:Type ms:DiagramSurface}}}" Value="False"> <Setter TargetName="Connector" Property="Visibility" Value="Collapsed" /> <Setter TargetName="Connectors" Property="Visibility" Value="Collapsed" /> </DataTrigger> <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Binding="{Binding Path=(ms:CursorAction.Current), Converter={StaticResource CursorActionTypeConverter}, RelativeSource={RelativeSource AncestorType={x:Type ms:DiagramSurface}}}" Value="{x:Static ms:CursorActionType.CreateConnection}" /> <Condition Binding="{Binding IsReadOnly, RelativeSource={RelativeSource AncestorType={x:Type ms:DiagramSurface}}}" Value="False" /> </MultiDataTrigger.Conditions> <Setter TargetName="Mover" Property="IsHitTestVisible" Value="False" /> <Setter TargetName="Connector" Property="IsHitTestVisible" Value="True" /> <Setter TargetName="Connector" Property="Visibility" Value="Visible" /> </MultiDataTrigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>
Â
Phew! That’s a lot of XAML! Good news though – you only need to tweak parts of it to start styling your own nodes.
After modifying the parts of the style that you need to customize, you then need to tell the DiagramSurface that this is the style you want to use. This is easily done by setting the NodeStyleSelector property of the IDiagramFormatter that you give to the DiagramSurface. If you wanted to use your style on all the different types of nodes in a diagram, then you would use the following code.
<ms:FixedStyleSelector x:Key="{x:Static styles:GradientStyle.NodeStyleSelectorKey}" Style="{StaticResource NodeStyle}" />So why make your own node element style?
The node element style is the best way to incorporate your own SizeThumb and ConnectionPointThumb styles on your nodes. This is done simply by making your own style for these thumbs, and then setting them on the appropriate controls found within the node element style. This allows you to achieve the effects in the following images.
![]()
Changing the color of the Resizer, and only including the corner thumbs.
![]()
Changing the look of the outbound connection point thumbs to have a transparent green fill.
Another useful tip with creating your own node styles is to add MouseDoubleClick or MouseRightButtonDown event handlers to the MoveThumb within the style. This will allow you to define appropriate actions to occur when the user double clicks or right click on a node. And since the MoveThumb in the standard node style is the most exposed control, it is the best place to attach such event handlers.
Node element styles are not limited to being applied to all the nodes in a single diagram. By using a TypeStyleSelector instead of a FixedStyleSelector, you can have some types nodes with different colored connection points compared to other nodes. Or some nodes could have the standard Resizer, while other nodes use a Resizer that only allows nodes to be square shaped.
Need any help with making your own node element styles? Drop a comment on this blog or put a post up on the forum. We’d love to hear from you!
Want to play with WPF Diagrams? Download the free trials of WPF Flow Diagrams or WPF Star Diagrams.
Leave a Reply
![]()
BrainDump (1)
Community Code (1)
Events (7)
General (35)
Lab Samples (2)
LightSpeed (146)
MegaPack (3)
News (52)
NHibernate Designer (4)
Products (69)
Projects (4)
Screencast (6)
SharePoint (2)
Silverlight (7)
Silverlight Elements (14)
SimpleDB Management Tools (13)
Visual Studio (4)
VS File Explorer (6)
WPF (34)
WPF Diagramming (17)
WPF Elements (30)
WPF Property Grid (26)
![]()
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
March 2009
February 2009
January 2009
December 2008
November 2008
October 2008
September 2008
August 2008
July 2008
June 2008
May 2008
April 2008
March 2008
February 2008
January 2008
December 2007
November 2007
September 2007
August 2007
July 2007
June 2007
May 2007
April 2007
March 2007





Posted by Jason on 29 September 2009


