Edit this page

Customize the Rotation Step

In RadDiagram each RadDiagramItem can be rotated. This operation is implemented by a RotationService.

In order to learn more about the different Diagramming Services, you can examine the Services article.

In this tutorial we will examine a solution that takes a user-defined value and uses it to define the step of a rotation operation in a RadDiagram instance.

First, let's create a sample RadDiagram definition that has two RadDiagramShape objects.

XAML

<telerik:RadDiagram x:Name="diagram" IsSnapToGridEnabled="False">
    <telerik:RadDiagramShape Geometry="{telerik:FlowChartShape ShapeType=BeginLoopShape}"
                             Position="400 300" />
    <telerik:RadDiagramShape Geometry="{telerik:FlowChartShape ShapeType=ExternalDataShape}"
                             Position="500 400" />
</telerik:RadDiagram>

Please note that in the RadDiagram definition, the SnapToGrid feature is disabled. If you enable it, you don't have to create a new RotationService to customize the rotation step. Instead you can take advantage of the RotationAngleSnap constant. It allows you to set the snapping angle when rotating items in a grid-snapping enabled RadDiagram. The default value of this constant is 5 degrees. And it can be easily changed by setting DiagramConstants.RotationAngleSnap = 55, but you will have to add a using statement for the Telerik.Windows.Diagrams.Core namespace.

Next we can add a TextBox control to let the user define the rotation step:

XAML

<StackPanel Width="200" HorizontalAlignment="Left">
    <TextBlock FontSize="16"
               FontWeight="Bold"
               Text="Rotating: " />
    <TextBox x:Name="rotationStep"
             MaxWidth="160"
             Text="" />
</StackPanel>

Now that our view is ready, we can configure the default rotation mechanism to take into account the rotation step defined by a user. In order to do so, we will have to create a custom RotationService and use it within our diagramming instance.

The first step is to define a new class, let's call it MyRotation, that derives from the RotationService. As the RotationService has a virtual method that calculates the angle of each rotation operation, we will override this method and implement logic that takes a user-defined value and uses it to calculate the rotation angle. This means that we need to define an int property and use it in the CalculateRotationAngle method implementation:

C#

public class MyRotation : RotationService
{
    private int rotationStep;

    public MyRotation(RadDiagram owner)
        : base(owner as IGraphInternal)
    {
        //initialize the RotationStep property
        this.RotationStep = 1;
    }

    public int RotationStep
    {
        get
        {
            return this.rotationStep;
        }
        set
        {
            this.rotationStep = value;
        }
    }

    protected override double CalculateRotationAngle(Point newPoint)
    {
        //take the angle calculated by the default rotation mechanism
        var angle = base.CalculateRotationAngle(newPoint);
        //change that angle based on the user-defined value of the RotationStep property
        return angle = Math.Floor(angle / this.RotationStep) * this.RotationStep;
    }
}

VB.NET

Public Class MyRotation
    Inherits RotationService

    Private rStep As Integer

    Public Sub New(ByVal owner As RadDiagram)
        MyBase.New(TryCast(owner, IGraphInternal))
        Me.RotationStep = 1
    End Sub

    Public Property RotationStep() As Integer
        Get
            Return Me.rStep
        End Get
        Set(ByVal value As Integer)
            Me.rStep = value
        End Set
    End Property

    Protected Overrides Function CalculateRotationAngle(ByVal newPoint As Point) As Double
        Dim angle = MyBase.CalculateRotationAngle(newPoint)
        angle = Math.Floor(angle / Me.RotationStep) * Me.RotationStep
        Return angle
    End Function
End Class

Finally, we need to configure the diagram to use our custom rotation implementation instead of the default RotationService. This is why we need to create a new instance of the MyRotation class in the code-behind file of our view. Then we need to make sure that the RotationStep property is used as a binding path for the Text property of the rotationStep:

C#

private MyRotation newRotationService;
private void InitializeNewServices()
{
    //initialize the newRotationService and define a default RotationStep
    this.newRotationService = new MyRotation(this.diagram) { RotationStep = 45 };
    //create a binding with Path=RotationStep
    Binding binding = new Binding("RotationStep");
    //use the newRotationService as a source of the binding
    binding.Source = this.newRotationService;
    binding.Mode = BindingMode.TwoWay;
    //apply the binding on the rotationStep TextBox
    this.rotationStep.SetBinding(TextBox.TextProperty, binding);
}

VB.NET

Private newRotationService As MyRotation
Private Sub InitializeNewServices()

    'initialize the newRotationService and define a default RotationStep'
    Me.newRotationService = New MyRotation(Me.diagram) With {
        .RotationStep = 45
    }
    'create a binding with Path=RotationStep'
    Dim binding As New Binding("RotationStep")
    'use the newRotationService as a source of the binding'
    binding.Source = Me.newRotationService
    binding.Mode = BindingMode.TwoWay
    'apply the binding on the rotationStep TextBox'
    Me.rotationStep.SetBinding(TextBox.TextProperty, binding)
End Sub

And now we can use the newRotationService instance and register it through the ServiceLocator:

C#

private MyRotation newRotationService;
public Example()
{
    InitializeComponent();

    this.InitializeNewServices();
    this.diagram.ServiceLocator.Register<IRotationService>(this.newRotationService);
}

VB.NET

Private newRotationService As MyRotation

Public Sub New()
    InitializeComponent()

    Me.InitializeNewServices()
    Me.diagram.ServiceLocator.Register(Of IRotationService)(Me.newRotationService)
End Sub

If you run the solution now, the rotationStep will display a value of 45. This is why you will be able to rotate the RadDiagramShapes with 45° on every step.

raddiagram-howto-custom-rotation-def Value

And if you enter a RotationStep of 90, you will be able to rotate the RadDiagramShapes with 90° on every step.
raddiagram-howto-custom-rotation

You can download a runnable project of the demonstrated example from our online SDK repository here, after navigating to Diagram/CustomServices.

See Also