Positioning and Appearance in WPF Diagram (SfDiagram)

Diagram allows you to customize the position and appearance of the annotation efficiently.

How to position node’s annotation

Annotation can be aligned relative to the node boundaries. It has Margin, Offset, Horizontal, and Vertical alignment settings. It is quite tricky when all four alignments are used together but gives more control over alignments properties of AnnotationEditorViewModel class.

Annotations of a node can be positioned using the following properties of AnnotationEditorViewModel class.

  • Offset
  • HorizontalAlignment and VerticalAlignment
  • Margin

Offset

The Offset property of AnnotationEditorViewModel is used to align the annotations based on fractions. 0 represents top-left corner, 1 represents bottom-right corner, and 0.5 represents half of width/height. Default value is (0.5, 0.5).

<!--Initialize the Node-->
<syncfusion:NodeViewModel UnitHeight="100" UnitWidth="100" 
                          Shape="{StaticResource Rectangle}" 
                          OffsetX="100" OffsetY="100">
    <syncfusion:NodeViewModel.Annotations>
        <!--Initialize the Annotation Collection-->
        <syncfusion:AnnotationCollection>
            <!--Initialize the annotation with offset values-->
            <syncfusion:AnnotationEditorViewModel Content="Offset(0,0)" 
                                                  Offset="0,0"/>
        </syncfusion:AnnotationCollection>
    </syncfusion:NodeViewModel.Annotations>
</syncfusion:NodeViewModel>
//Initialize the NodeViewModel
NodeViewModel node = new NodeViewModel()
{
    UnitWidth = 100,
    UnitHeight = 100,
    Shape = new RectangleGeometry() { Rect = new Rect(0, 0, 10, 10) },
    OffsetX = 100,
    OffsetY = 100,
    //Initialize the Annotation Collection
    Annotations = new ObservableCollection<IAnnotation>()
    {
        //Initialize the annotation with offset values
        new AnnotationEditorViewModel()
        {
            Content = "Offset(0,0)",
            Offset = new Point(0,0),
        },
    }
};
Offset values Output
(0,0) Left
(0,0.5) Left
(0,1) Left
(0.5,0) Left
(0.5,0.5) Left
(0.5,1) Left
(1,0) Left
(1,0.5) Left
(1,1) Left

Horizontal and vertical Alignments

The HorizontalAlignment property of AnnotationEditorViewModel class is used to align the annotation horizontally. Default value is Center.

The VerticalAlignment property of AnnotationEditorViewModel class is used to align the annotation vertically. Default value is Center.

<!--Initialize the Annotation Collection-->
<syncfusion:AnnotationCollection>
    <!--Initialize the Annotation with horizontal and vertical alignment properties-->
    <syncfusion:AnnotationEditorViewModel Content="Annotation" 
                                          HorizontalAlignment="Left" 
                                          VerticalAlignment="Top" 
                                          Offset="0,0"/>
</syncfusion:AnnotationCollection>
//Initialize the Annotation Collection
Annotations = new ObservableCollection<IAnnotation>()
{
    //Initialize the Annotation with horizontal and vertical alignment properties
    new AnnotationEditorViewModel()
    {
        Content = "Annotation",
        HorizontalAlignment = HorizontalAlignment.Left,
        VerticalAlignment = VerticalAlignment.Top,
        Offset = new Point(0,0),
    }
}
Horizontal Alignment Vertical Alignment Output with Offset(0,0)
Left Top Left
Center Top Center
Right Top Right
Left Center Left Center
Center Center Center
Right Center Right
Left Bottom Left
Center Bottom Center
Right Bottom Right

Margin

Margin is an absolute value used to add some blank space in any one of its four sides. The annotations can be displaced with the margin property. The following code example explains how to align an annotation based on its Margin value. Default value is (0,0,0,0).

<!--Initialize the Annotation Collection-->
<syncfusion:AnnotationCollection>
    <!--Initialize the Annotation with margin property-->
    <syncfusion:AnnotationEditorViewModel Content="Annotation" Margin="0,60,0,0"/>
</syncfusion:AnnotationCollection>
//Initialize the Annotation Collection
Annotations = new ObservableCollection<IAnnotation>()
{
    //Initialize the Annotation with margin property
    new AnnotationEditorViewModel()
    {
        Content = "Annotation",
        Margin = new Thickness(0, 60, 0, 0),
    }
}

Margin

How to position connector’s annotation

Annotations of a connector can be positioned using the following properties of AnnotationEditorViewModel class:

  • Alignment
  • Length
  • Displacement
  • Pivot
  • Margin

Alignment

Connector’s annotation can be aligned over its segment path using the Alignment property of AnnotationEditorViewModel class. Default value is Center.

<!--Initialize the AnnotationCollection-->
<syncfusion:AnnotationCollection>
    <!--Initialize the Annotation with alignment property-->
    <syncfusion:AnnotationEditorViewModel Content="Annotation" Alignment="Source" />
</syncfusion:AnnotationCollection>
//Initialize the Annotation Collection
Annotations = new ObservableCollection<IAnnotation>()
{
    //Initialize the Annotation with alignment property
    new AnnotationEditorViewModel()
    {
        Content = "Annotation",
        Alignment = ConnectorAnnotationAlignment.Source,
    }
}
Property Value Output
Alignment Source Source
  Center Center
  Target Target

Length

The Length property of annotation is used to align the annotations based on fractions. 0 represents Top-Left corner, 1 represents Bottom-Right corner, and 0.5 represents half of Width/Height. The default value is 0.5d.

<!--Initialize the Annotation Collection-->
<syncfusion:AnnotationCollection>
    <!--Initialize the Annotation with length property-->
    <syncfusion:AnnotationEditorViewModel Content="Annotation" Length="0" />
</syncfusion:AnnotationCollection>
//Initialize the Annotation Collection
Annotations = new ObservableCollection<IAnnotation>()
{
    //Initialize the Annotation with length property
    new AnnotationEditorViewModel()
    {
        Content = "Annotation",
        Length = 0,
    }
}

The following image shows the relationship between the annotation position and Length (fraction values).

Length

Displacement

The Displacement property is used to dislocate the annotation by the value given. By default, annotation will be in center of the connector path. When you assign value to the Displacement property, annotation will be displaced from its position by displacment value. Default value is 0d.

<!--Initialize the Annotation ollection-->
<syncfusion:AnnotationCollection>
    <!--Initialize the Annotation with dispalcement property-->
    <syncfusion:AnnotationEditorViewModel Content="Annotation" Displacement="60" />
</syncfusion:AnnotationCollection>
//Initialize the Annotation Collection
Annotations = new ObservableCollection<IAnnotation>()
{
    //Initialize the Annotation with dispalcement property
    new AnnotationEditorViewModel()
    {
        Content = "Annotation",
        Displacement = 60
    }
}
Property Value Output
Displacement 0 Source
  60 Center
  -60 Target

Pivot

Position of an annotation is controlled by using its Length property, which represents the distance from connector center. The Pivot property is used to align the annotation based on its center point. Default value of the pivot point is (0.5, 0.5), that means center of length.

<!--Initialize the Annotation Collection-->
<syncfusion:AnnotationCollection>
    <!--Initialize the Annotation with pivot property-->
    <syncfusion:AnnotationEditorViewModel Content="Annotation" Pivot="0,0" Length="0" />
</syncfusion:AnnotationCollection>
//Initialize the Annotation Collection
Annotations = new ObservableCollection<IAnnotation>()
{
    //Initialize the Annotation with pivot property
    new AnnotationEditorViewModel()
    {
        Content = "Annotation",
        Pivot = new Point(0,0),
        Length = 0,
    }
}
Property Value Output with 0 Length value
Pivot (0.5,0.5) Target
  (0,0) Source
  (0,1) Center
  1,0) Target
  (1,1) Target

Margin

Margin is an absolute value used to add some blank space in any one of its four sides. You can displace the annotations with the Margin property. Default value is (0,0,0,0).

<!--Initialize the Annotation Collection-->
<syncfusion:AnnotationCollection>
    <!--Initialize the annotation with margin property-->
    <syncfusion:AnnotationEditorViewModel  Content="Annotation" 
                                           Margin="0,0,0,-30" 
                                           RotationReference="Page" />
</syncfusion:AnnotationCollection>
//Initialize the AnnotationCollection
Annotations = new ObservableCollection<IAnnotation>()
{
    new AnnotationEditorViewModel()
    {
        Content="Annotation",
        //Initialize the margin property
        Margin = new Thickness(0,0,0,-30),
        // Decide to apply orientation or rotation based on segment when annotation is positioned.
        RotationReference = RotationReference.Page,
    }
}

ConnectorAnnotationMargin

How to set size for annotation

Diagram allows you to set size for annotations by using the UnitWidth and UnitHeight properties. Default value of UnitWidth and UnitHeight properties are double.NaN.

<!--Initialize the AnnotationCollection-->
<syncfusion:AnnotationCollection>
    <!--Initialize the annotation wih size-->
    <syncfusion:AnnotationEditorViewModel Content="Annotation" 
                                          UnitWidth="50" UnitHeight="50" />
</syncfusion:AnnotationCollection>
//Initialize the AnnotationCollection
Annotations = new ObservableCollection<IAnnotation>()
{
    new AnnotationEditorViewModel()
    {
        Content="Annotation",
        //Set the size of annotation
        UnitWidth = 50,
        UnitHeight = 50,
    }
}

NodeSize      ConnectorSize

NOTE

Size of the annotation is 100% size of the node.

Wrapping

When text overflows node boundaries, you can control it by using the WrapText property. So, it is wrapped into multiple lines. The Wrapping property of annotation defines how the content should be wrapped. Default value is Wrap.

<!--Initialize the Annotation Collection-->
<syncfusion:AnnotationCollection>
    <!--Initialize the annotation with wrap text property-->
    <syncfusion:AnnotationEditorViewModel Content="LengthyAnnotation with wrapping text" 
                                          WrapText="Wrap"/>
</syncfusion:AnnotationCollection>
//Initialize the Annotation Collection
Annotations = new AnnotationCollection()
{
    new AnnotationEditorViewModel()
    {
        Content = "LengthyAnnotation with wrapping text",
        //Define the value for wrap text property
        WrapText=TextWrapping.Wrap,
    }
}
Values Description Node
NoWrap Text will not be wrapped. NoWrap
Wrap Text-wrapping occurs when the text overflows beyond the available annotation container width. Wrap
WrapWithOverflow Text-wrapping occurs when the text overflows beyond the available annotation container width. However, the text may overflow beyond the annotation container width in the case of a very long word. Overflow

How to change the appearance of annotation

Default appearance of the annotations can be customized by using the EditTemplate and ViewTemplate properties. ViewTemplate is used to control the appearance of the annotation when it is in non-editing stage. EditTemplate is used to control the appearance of the annotation while it is in editing.

<!--Template overriding for view template-->
<DataTemplate x:Key="viewTemplate">
    <TextBlock Text="{Binding Path=Content, Mode=TwoWay}" 
               FontStyle="Italic" FontSize="12" 
               FontFamily="TimesNewRomen" 
               TextDecorations="Underline" 
               FontWeight="Bold" 
               Foreground="Black"/>
</DataTemplate>

<!--Template overriding for edit template-->
<DataTemplate x:Key="editTemplate">
    <TextBox Text="{Binding Path=Content, Mode=TwoWay}" 
             FontStyle="Oblique" FontSize="12" 
             FontFamily="TimesNewRomen" 
             FontWeight="Bold" Foreground="Red"/>
</DataTemplate>

<!--Initialize the Annotation Collection-->
<syncfusion:AnnotationCollection>
    <!--Initialize the Annotation with view and edit templates-->
    <syncfusion:AnnotationEditorViewModel Content="Annotation" 
                                          ViewTemplate="{StaticResource viewTemplate}" 
                                          EditTemplate="{StaticResource editTemplate}"/>
</syncfusion:AnnotationCollection>
//Initialize the AnnotationCollection
Annotations = new ObservableCollection<IAnnotation>()
{
    new AnnotationEditorViewModel()
    {
        Content = "Annotation",
        //Defines the view and edit templates
        ViewTemplate = App.Current.Resources["viewTemplate"] as DataTemplate,
        EditTemplate  = App.Current.Resources["editTemplate"] as DataTemplate,
    }
}

Appearance       Appearance

Also, diagram have TextAnnotationViewModel class to customize the appearance of the annotation directly instead of overriding view and edit templates of the annotation. This class customization will be applied for both view and edit mode of annotation.

<!--Initialize the Annotation Collection-->
<syncfusion:AnnotationCollection>
    <!--Initialize the Text Annotation View Model class-->
    <syncfusion:TextAnnotationViewModel Text="Annotation" FontStyle="Italic" 
                                        FontSize="12" FontFamily="TimesNewRomen" 
                                        TextDecorations="Underline" 
                                        FontWeight="Bold" Foreground="Black"/>
</syncfusion:AnnotationCollection>
//Initialize the Annotation Collection
Annotations = new ObservableCollection<IAnnotation>()
{
    //Intialize the Text Annotation View Model class
    new TextAnnotationViewModel()
    {
        Text = "Annotation",
        FontStyle = FontStyles.Italic,
        FontSize = 12,
        FontFamily = new FontFamily("TimesNewRomen"),
        TextDecorations = TextDecorations.Underline,
        FontWeight = FontWeights.Bold,
        Foreground = new SolidColorBrush(Colors.Black),
    }
}

Appearance       Appearance

How to change the editing mode

Diagram allows you to show the annotation in view or edit mode while loading the diagram elements by using the Mode property of AnnotationEditorViewModel class. Default value is View.

<!--Initialize the Annotation Collection-->
<syncfusion:AnnotationCollection>
    <!--Initialize the Annotation with edit mode property-->
    <syncfusion:AnnotationEditorViewModel Content="Annotation" Mode="Edit"/>
</syncfusion:AnnotationCollection>
//Initialize the Annotation Collection
Annotations = new ObservableCollection<IAnnotation>()
{
    new AnnotationEditorViewModel()
    {
        Content = "Annotation",
        //Initialize the editing mode property
        Mode = ContentEditorMode.Edit,
    }
}

Appearance

NOTE

Edit mode will be applied to a single element at a time.

How to edit the annotation

Annotation will be in editing state when you double click the node or annotation. Annotation will be selected when you single click the annotation if selectable constraints are enabled.

Also, the ReadOnly property of AnnotationEditorViewModel class allows you to disable the editing option of annotation.

<!--Initialize the Annotation Collection-->
<syncfusion:AnnotationCollection>
    <!--Initialize the annotation with read only property-->
    <syncfusion:AnnotationEditorViewModel Content="Annotation" ReadOnly="True"/>
</syncfusion:AnnotationCollection>
//Initialize the Annotation Collection
Annotations = new ObservableCollection<IAnnotation>()
{
    new AnnotationEditorViewModel()
    {
        Content = "Annotation",
        //Initialize the ReadOnly property
        ReadOnly = true,
    }
}