In this tutorial we will create a custom CompositeNode class which will be able to display information about individuals in an organization - such as name, description and image. The node will be customizable through various exposed properties.
1. Declaring the custom class
To create a custom composite node simply derive from the CompositeNode class.
C#
Copy Code
|
---|
public class OrgChartNode : CompositeNode { } |
Visual Basic
Copy Code
|
---|
Public Class OrgChartNode Inherits CompositeNode
End Class |
Creating a custom node is applicable in various scenarios. For example, if you want to define the contents of the node in XML and want to declare event handlers for various components. Or if you want to apply custom component arrangement logic or custom rendering.
2. Specifying the component content
Add a single constructor to the newly created node class with the following contents:
C#
Copy Code
|
---|
... public OrgChartNode(Diagram diagram) : base(diagram) { string content = @" <SimplePanel>
<Shape Name=""Shape"" Shape=""Rectangle"" />
<Border Padding=""2""> <GridPanel> <GridPanel.Columns> <GridColumn Width=""30"" /> <GridColumn /> </GridPanel.Columns> <GridPanel.Rows> <GridRow /> </GridPanel.Rows>
<Image Name=""Image"" ImageAlign=""Fit"" />
<StackPanel Orientation=""Vertical"" GridColumn=""1""> <Text Name=""Title"" Font=""Arial, 12pt, style=Bold"" TextAlignment=""Near"" /> <Text Name=""FullName"" TextColor=""Blue"" TextAlignment=""Near"" /> <Text Name=""Text"" Font=""Arial, 8pt"" TextAlignment=""Near"" /> </StackPanel> </GridPanel> </Border>
</SimplePanel>";
Components.Add(XmlLoader.Load(content, null, null)); } ... |
Visual Basic
Copy Code
|
---|
... Public Sub New(ByVal diagram As Diagram)
MyBase.new(diagram)
Dim content As String = _ "<SimplePanel>" & _ "" & _ " <Shape Name=""Shape"" Shape=""Rectangle"" />" & _ "" & _ " <Border Padding=""2"">" & _ " <GridPanel>" & _ " <GridPanel.Columns>" & _ " <GridColumn Width=""30"" />" & _ " <GridColumn />" & _ " </GridPanel.Columns>" & _ " <GridPanel.Rows>" & _ " <GridRow />" & _ " </GridPanel.Rows>" & _ "" & _ " <Image Name=""Image"" ImageAlign=""Fit"" />" & _ "" & _ " <StackPanel Orientation=""Vertical"" GridColumn=""1"">" & _ " <Text Name=""Title"" Font=""Arial, 12pt, style=Bold"" TextAlignment=""Near"" />" & _ " <Text Name=""FullName"" TextColor=""Blue"" TextAlignment=""Near"" />" & _ " <Text Name=""Text"" Font=""Arial, 8pt"" TextAlignment=""Near"" />" & _ " </StackPanel>" & _ " </GridPanel>" & _ " </Border>" & _ "" & _ "</SimplePanel>"
Components.Add(XmlLoader.Load(content, Nothing, Nothing))
End Sub ... |
3. Declaring component fields
Now that the content of the node is defined and loaded, we will add several fields to our class referencing different components of interest. Add the following fields at the end of the class:
C#
Copy Code
|
---|
private ShapeComponent shape; private ImageComponent image; private TextComponent title; private TextComponent fullName; private TextComponent text; |
Visual Basic
Copy Code
|
---|
Private _shape As ShapeComponent Private _image As ImageComponent Private _title As TextComponent Private _fullName As TextComponent Private _text As TextComponent |
To initialize the fields to reference the respective components, you can use the FindComponent method of the CompositeNode class. This method will operate successfully after the components are added to the node's Components collection. Add the following code in the constructor, after the components are connected to the composite node:
C#
Copy Code
|
---|
... Components.Add(XmlLoader.Load(content, null, null));
shape = FindComponent("Shape") as ShapeComponent; image = FindComponent("Image") as ImageComponent; title = FindComponent("Title") as TextComponent; fullName = FindComponent("FullName") as TextComponent; text = FindComponent("Text") as TextComponent; ... |
Visual Basic
Copy Code
|
---|
... Components.Add(XmlLoader.Load(content, Nothing, Nothing))
_shape = CType(FindComponent("Shape"), ShapeComponent) _image = CType(FindComponent("Image"), ImageComponent) _title = CType(FindComponent("Title"), TextComponent) _fullName = CType(FindComponent("FullName"), TextComponent) _text = CType(FindComponent("Text"), TextComponent) ... |
4. Defining node properties
To be able to customize the node, we need to expose several properties. In this case the properties will act merely as wrappers of properties of the underlying components. For example, the Stroke property will wrap the Pen property of the underlying ShapeComponent used as a background. This way we can allow the user to customize the node without exposing its internal component structure directly.
Add the following properties after the constructor.
C#
Copy Code
|
---|
public MindFusion.Drawing.Pen Stroke { get { return shape.Pen; } set { shape.Pen = value; } }
public MindFusion.Drawing.Brush Fill { get { return shape.Brush; } set { shape.Brush = value; } }
public Image Image { get { return image.Image; } set { image.Image = value; } }
public string Title { get { return title.Text; } set { title.Text = value; } }
public string FullName { get { return fullName.Text; } set { fullName.Text = value; } }
public string Text { get { return text.Text; } set { text.Text = value; } } |
Visual Basic
Copy Code
|
---|
Public Property Stroke() As MindFusion.Drawing.Pen
Get Return _shape.Pen End Get Set(ByVal value As MindFusion.Drawing.Pen) _shape.Pen = value End Set
End Property
Public Property Fill() As MindFusion.Drawing.Brush
Get Return _shape.Brush End Get Set(ByVal value As MindFusion.Drawing.Brush) _shape.Brush = value End Set
End Property
Public Property Image() As Image
Get Return _image.Image End Get Set(ByVal value As Image) _image.Image = value End Set
End Property
Public Property Title() As String
Get Return _title.Text End Get Set(ByVal value As String) _title.Text = value End Set
End Property
Public Property FullName() As String
Get Return _fullName.Text End Get Set(ByVal value As String) _fullName.Text = value End Set
End Property
Public Property Text() As String
Get Return _text.Text End Get Set(ByVal value As String) _text.Text = value End Set
End Property |
5. Specifying default values
The default values can be provided in the constructor, after the component content have been loaded and the reference to the components of interest have been obtained. The following code sets White background and Black border as default values of new nodes.
C#
Copy Code
|
---|
Stroke = new MindFusion.Drawing.Pen(Color.Black, 0); Fill = new MindFusion.Drawing.SolidBrush(Color.White); |
Visual Basic
Copy Code
|
---|
Stroke = New MindFusion.Drawing.Pen(Color.Black, 0) Fill = New MindFusion.Drawing.SolidBrush(Color.White) |
This concludes the implementation of our custom node class.
6. Using the custom node class
Assuming that we have a ready WinForms application containing a Diagram variable named diagram1, and that two images have been added as resources to this application - named respectively Image1 and Image2, the following code creates two new instances of the OrgChartNode class and connects them with a link:
C#
Copy Code
|
---|
OrgChartNode node1 = new OrgChartNode(diagram1); node1.Bounds = new RectangleF(20, 10, 80, 40); node1.Title = "CEO"; node1.FullName = "John Smith"; node1.Text = "Our beloved leader. \r\n" + "The CEO of this great corporation."; node1.Image = Properties.Resources.Image1; diagram1.Nodes.Add(node1);
OrgChartNode node2 = new OrgChartNode(diagram1); node2.Bounds = new RectangleF(60, 60, 80, 40); node2.Title = "CIO"; node2.FullName = "Bob Smith"; node2.Text = "The CIO of this great corporation."; node2.Image = Properties.Resources.Image2; diagram1.Nodes.Add(node2);
diagram1.Factory.CreateDiagramLink(node1, node2); |
Visual Basic
Copy Code
|
---|
Dim node1 As New OrgChartNode(diagram1) node1.Bounds = New RectangleF(20, 10, 80, 40) node1.Title = "CEO" node1.FullName = "John Smith" node1.Text = "Our beloved leader. \r\n" & _ "The CEO of this great corporation." node1.Image = My.Resources.Image1 diagram1.Nodes.Add(node1)
Dim node2 = New OrgChartNode(diagram1) node2.Bounds = New RectangleF(60, 60, 80, 40) node2.Title = "CIO" node2.FullName = "Bob Smith" node2.Text = "The CIO of this great corporation." node2.Image = My.Resources.Image2 diagram1.Nodes.Add(node2)
diagram1.Factory.CreateDiagramLink(node1, node2) |
Running the application will give results similar to the image below: