Restrict the Draggable Area
The Diagramming Framework implements a DraggingService that controls and configures the drag operations on the diagram surface.
In order to learn more about the different Diagramming Services, you can examine the Services article.
This tutorial demonstrates how to customize the default dragging operation and restrict the draggable area so that a shape can only be moved within a predefined range in the diagramming surface.
In order to implement such a scenario, we will need a sample RadDiagram instance with two RadDiagramShapes, a Rectangle that describes the draggable area within the diagram and a few buttons to give the user control over the drag operation.
The scenario described below will provide the user with the following options:
Drag shapes only while the mouse is within a predefined draggable area.
Drag shapes only within a predefined draggable area by making sure that no part of the shape is outside this area.
Take into account the rotated bounds of a shape when dragging it in a predefined draggable area.
<Grid Background="White">
<telerik:RadDiagram x:Name="diagram">
<telerik:RadDiagramShape Geometry="{telerik:FlowChartShape ShapeType=BeginLoopShape}" Position="400 300" />
<telerik:RadDiagramShape Geometry="{telerik:FlowChartShape ShapeType=ExternalDataShape}" Position="500 400" />
</telerik:RadDiagram>
<Border x:Name="border"
Width="840"
Height="480"
BorderBrush="LightBlue"
BorderThickness="2" />
<StackPanel Width="200" HorizontalAlignment="Left">
<TextBlock FontSize="16"
FontWeight="Bold"
Text="Dragging: " />
<telerik:RadToggleButton x:Name="toggleDrag"
Width="130"
Height="30"
Content="On"
IsChecked="True" />
<telerik:RadToggleButton x:Name="IsRestrictedToBounds"
Width="130"
Height="30"
Content="IsRestrictedToBounds" />
<telerik:RadToggleButton x:Name="useRotaitonBounds"
Width="130"
Height="30"
Content="UseRotatedBounds"
IsChecked="True" />
</StackPanel>
</Grid>
In order to restrict the RadDiagramShapes dragging area, you need to create a custom dragging service. This means that you have to start this implementation by creating a new class that derives from the DiagrammingFramework DraggingService class.
public class MyDragging : DraggingService
{
public MyDragging(RadDiagram graph)
: base(graph as IGraphInternal)
{
}
}
Public Class MyDragging
Inherits DraggingService
Public Sub New(ByVal graph As RadDiagram)
MyBase.New(TryCast(graph, IGraphInternal))
End Sub
End Class
Next, we need to add properties that will configure the dragging service from the UI. In this scenario we need to have the following set of properties:
IsRestrictedToBounds - a bool property that gets or sets a value determining whether the shapes should entirely be within the actual bounds of the draggable area.
UseRotaitonBounds - a bool property that gets or sets a value determining whether the rotation bounds of a shape should be taken into account when applying dragging restrictions. The rotation bounds are the actual bounds of a shape after rotation.
IsOn - a bool property that gets or sets a value determining whether to restrict the dragging within a predefined area.
DragAllowedArea - a Rect property that gets or sets a value representing the draggable area.
public class MyDragging : DraggingService, INotifyPropertyChanged
{
private bool isRestrictedToBounds;
private bool isOn;
private bool useRotationBounds;
public MyDragging(RadDiagram graph)
: base(graph as IGraphInternal)
{
//initialize the properties of the service
this.DragAllowedArea = Rect.Empty;
this.IsOn = true;
this.UseRotationBounds = true;
}
public event PropertyChangedEventHandler PropertyChanged;
public Rect DragAllowedArea { get; set; }
public bool IsRestrictedToBounds
{
get
{
return this.isRestrictedToBounds;
}
set
{
if (this.isRestrictedToBounds != value)
{
this.isRestrictedToBounds = value;
this.OnPropertyChanged("IsRestrictedToBounds");
}
}
}
public bool UseRotationBounds
{
get
{
return this.useRotationBounds;
}
set
{
if (this.useRotationBounds != value)
{
this.useRotationBounds = value;
this.OnPropertyChaged("UseRotationBounds");
}
}
}
public bool IsOn
{
get
{
return this.isOn;
}
set
{
if (this.isOn != value)
{
this.isOn = value;
this.OnPropertyChaged("IsOn");
}
}
}
private void OnPropertyChanged(string name)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
}
Public Class MyDragging
Inherits DraggingService
Implements INotifyPropertyChanged
Private restrictedToBounds As Boolean
Private isOnValue As Boolean
Private useRotateBounds As Boolean
Public Sub New(ByVal graph As RadDiagram)
MyBase.New(TryCast(graph, IGraphInternal))
Me.DragAllowedArea = Rect.Empty
Me.IsOn = True
Me.UseRotaitonBounds = True
End Sub
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Public Property DragAllowedArea() As Rect
Public Property IsRestrictedToBounds() As Boolean
Get
Return Me.restrictedToBounds
End Get
Set(ByVal value As Boolean)
If Me.restrictedToBounds <> value Then
Me.restrictedToBounds = value
Me.OnPropertyChaged("IsRestrictedToBounds")
End If
End Set
End Property
Public Property UseRotaitonBounds() As Boolean
Get
Return Me.useRotateBounds
End Get
Set(ByVal value As Boolean)
If Me.useRotateBounds <> value Then
Me.useRotateBounds = value
Me.OnPropertyChaged("UseRotaitonBounds")
End If
End Set
End Property
Public Property IsOn() As Boolean
Get
Return Me.isOnValue
End Get
Set(ByVal value As Boolean)
If Me.isOnValue <> value Then
Me.isOnValue = value
Me.OnPropertyChaged("IsOn")
End If
End Set
End Property
Private Sub OnPropertyChaged(ByVal name As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(name))
End Sub
End Class
The DraggingService exposes a virtual method - Drag, which can be overridden to customize the default drag operation. In this method we will have to handle all restriction cases.
First, if we need to only restrict the position of the mouse while dragging a shape, then we have to simply track that position and check whether it falls within the bounds of the draggable area. If it doesn't we have to create a property to hold an updated and most importantly - allowed mouse position. Please note that all position calculations will be based on the coordinate system of the diagramming instance:
public override void Drag(Point newPoint)
{
Point dragPoint = newPoint;
//if the mouse position during a drag operation should be restricted within the DragAllowedArea
if (this.DragAllowedArea != Rect.Empty && !this.DragAllowedArea.Contains(newPoint))
{
//calculate the proper position of the dragPoint
double X = dragPoint.X;
double Y = dragPoint.Y;
if (X > this.DragAllowedArea.Right)
X = this.DragAllowedArea.Right;
else if (X < this.DragAllowedArea.Left)
X = this.DragAllowedArea.Left;
if (Y > this.DragAllowedArea.Bottom)
Y = this.DragAllowedArea.Bottom;
else if (Y < this.DragAllowedArea.Top)
Y = this.DragAllowedArea.Top;
dragPoint = new Point(X, Y);
}
}
Public Overrides Sub Drag(ByVal newPoint As Point)
Dim dragPoint As Point = newPoint
'if the mouse position during a drag operation should be restricted within the DragAllowedArea'
If Me.DragAllowedArea <> Rect.Empty AndAlso (Not Me.DragAllowedArea.Contains(newPoint)) Then
'calculate the proper position of the dragPoint'
Dim X As Double = dragPoint.X
Dim Y As Double = dragPoint.Y
If X > Me.DragAllowedArea.Right Then
X = Me.DragAllowedArea.Right
ElseIf X < Me.DragAllowedArea.Left Then
X = Me.DragAllowedArea.Left
End If
If Y > Me.DragAllowedArea.Bottom Then
Y = Me.DragAllowedArea.Bottom
ElseIf Y < Me.DragAllowedArea.Top Then
Y = Me.DragAllowedArea.Top
End If
dragPoint = New Point(X, Y)
End If
End Sub
With the above code we calculate a new drag position only in the cases when the mouse leaves the designated dragging area. Although these calculations will not stop the mouse from moving across the diagramming surface, they will stop the selected shapes from being dragged further away.
However, if the user wants to configure the shapes to be entirely moved only within a draggable area, we will have to get the RadDiagram SelectionBounds. And in order to handle the case that takes into account the rotation of the selected shapes when calculating the SelectionBounds, it is best to create a separate method:
private readonly RadDiagram diagram;
//this method gets the bounds of the selected DiagramItems
private Rect GetSelectionBounds()
{
if (this.UseRotaitonBounds)
{
//find the selection bounds after a rotation
Rect result = Rect.Empty;
foreach (var item in this.diagram.SelectedItems)
{
var container = this.diagram.ContainerGenerator.ContainerFromItem(item);
var shape = item as IShape;
if (shape != null)
result.Union(shape.ActualBounds);
else
result.Union(container.Bounds);
}
return result;
}
else
{
//or get the default selection bounds
return this.diagram.SelectionBounds;
}
}
Private ReadOnly diagram As RadDiagram
'this method gets the bounds of the selected DiagramItems '
Private Function GetSelectionBounds() As Rect
If Me.UseRotaitonBounds Then
'find the selection bounds after a rotation'
Dim result As Rect = Rect.Empty
For Each item In Me.diagram.SelectedItems
Dim container = Me.diagram.ContainerGenerator.ContainerFromItem(item)
Dim shape = TryCast(item, IShape)
If shape IsNot Nothing Then
result.Union(shape.ActualBounds)
Else
result.Union(container.Bounds)
End If
Next item
Return result
Else
'or get the default selection bounds'
Return Me.diagram.SelectionBounds
End If
End Function
In the above implementation we added a diagram field which gets the RadDiagram instance currently using the dragging service. This is why we also have to initialize this field in the constructor of the service:
public MyDragging(RadDiagram graph)
: base(graph as IGraphInternal)
{
this.diagram = graph;
this.DragAllowedArea = Rect.Empty;
this.IsOn = true;
this.UseRotaitonBounds = true;
}
Public Sub New(ByVal graph As RadDiagram)
MyBase.New(TryCast(graph, IGraphInternal))
Me.diagram = graph
Me.DragAllowedArea = Rect.Empty
Me.IsOn = True
Me.UseRotaitonBounds = True
End Sub
Then we can use the GetSelectionBounds() method in the logic that customizes the drag of shapes which bounds need to always be within the predefined draggable area:
public override void Drag(Point newPoint)
{
Point dragPoint = newPoint;
if (this.IsRestrictedToBounds)
{
//get the bounds of the selected RadDiagramItems
var selectionBounds = this.GetSelectionBounds();
//find the drag offset by comparing the coordinates of the last and the new drag position
var offset = new Vector(newPoint.X - this.lastPoint.X, newPoint.Y - this.lastPoint.Y);
//calculate the new bounds of the dragged selected items
var newBounds = new Rect(selectionBounds.X + offset.X, selectionBounds.Y + offset.Y, selectionBounds.Width, selectionBounds.Height);
//if there is no predefined draggable area or
//if the bounds of the dragged selected items are within the predefined draggable area
//invoke the default implementation of the DraggingService Drag() method
if (this.DragAllowedArea == Rect.Empty || this.DragAllowedArea.Contains(newBounds))
{
base.Drag(newPoint);
this.lastPoint = dragPoint;
return;
}
//if the bounds of the selected items is outside the bounds of the draggable area,
//recalculate the coordinates of the drag point to make sure the bounds of the selected items is inside the draggable area
if (this.DragAllowedArea.Left > newBounds.Left)
dragPoint = new Point(dragPoint.X - (newBounds.Left - this.DragAllowedArea.Left), dragPoint.Y);
else if (this.DragAllowedArea.Right < newBounds.Right)
dragPoint = new Point(dragPoint.X - (newBounds.Right - this.DragAllowedArea.Right), dragPoint.Y);
if (this.DragAllowedArea.Top > newBounds.Top)
dragPoint = new Point(dragPoint.X, dragPoint.Y - (newBounds.Top - this.DragAllowedArea.Top));
else if (this.DragAllowedArea.Bottom < newBounds.Bottom)
dragPoint = new Point(dragPoint.X, dragPoint.Y - (newBounds.Bottom - this.DragAllowedArea.Bottom));
}
}
Public Overrides Sub Drag(ByVal newPoint As Point)
Dim dragPoint As Point = newPoint
'if the actual bounds of the shape should be within the DragAllowedArea'
If Me.IsRestrictedToBounds Then
'get the bounds of the selected RadDiagramItems'
Dim selectionBounds = Me.GetSelectionBounds()
'find the drag offset by comparing the coordinates of the last and the new drag position '
Dim offset = New Vector(newPoint.X - Me.lastPoint.X, newPoint.Y - Me.lastPoint.Y)
'calculate the new bounds of the dragged selected items'
Dim newBounds = New Rect(selectionBounds.X + offset.X, selectionBounds.Y + offset.Y, selectionBounds.Width, selectionBounds.Height)
'if there is no predefined draggable area or '
'if the bounds of the dragged selected items are within the predefined draggable area'
'invoke the default implementation of the DraggingService Drag() method'
If Me.DragAllowedArea = Rect.Empty OrElse Me.DragAllowedArea.Contains(newBounds) Then
MyBase.Drag(newPoint)
Me.lastPoint = dragPoint
Return
End If
'if the bounds of the selected items is outside the bounds of the draggable area, '
'recalculate the coordinates of the drag point to make sure the bounds of the selected items is inside the draggable area '
If Me.DragAllowedArea.Left > newBounds.Left Then
dragPoint = New Point(dragPoint.X - (newBounds.Left - Me.DragAllowedArea.Left), dragPoint.Y)
ElseIf Me.DragAllowedArea.Right < newBounds.Right Then
dragPoint = New Point(dragPoint.X - (newBounds.Right - Me.DragAllowedArea.Right), dragPoint.Y)
End If
If Me.DragAllowedArea.Top > newBounds.Top Then
dragPoint = New Point(dragPoint.X, dragPoint.Y - (newBounds.Top - Me.DragAllowedArea.Top))
ElseIf Me.DragAllowedArea.Bottom < newBounds.Bottom Then
dragPoint = New Point(dragPoint.X, dragPoint.Y - (newBounds.Bottom - Me.DragAllowedArea.Bottom))
End If
End If
End Sub
No matter which restriction approach we implement (restricting the drag based on the mouse position or the shapes bounds), we always end up recalculating the dragPoint coordinates. This is why as soon as we calculate a valid drag value, we need to invoke the base implementation of the DraggingService Drag() method with the new dragPoint. You can find the complete implementation of the overridden Drag() method below:
public override void Drag(Point newPoint)
{
Point dragPoint = newPoint;
if (this.IsOn)
{
//if the actual bounds of the shape should be within the DragAllowedArea
if (this.IsRestrictedToBounds)
{
//get the bounds of the selected RadDiagramItems
var selectionBounds = this.GetSelectionBounds();
//find the drag offset by comparing the coordinates of the last and the new drag position
var offset = new Vector(newPoint.X - this.lastPoint.X, newPoint.Y - this.lastPoint.Y);
//calculate the new bounds of the dragged selected items
var newBounds = new Rect(selectionBounds.X + offset.X, selectionBounds.Y + offset.Y, selectionBounds.Width, selectionBounds.Height);
//if there is no predefined draggable area or
//if the bounds of the dragged selected items are within the predefined draggable area
//invoke the default implementation of the DraggingService Drag() method
if (this.DragAllowedArea == Rect.Empty || this.DragAllowedArea.Contains(newBounds))
{
base.Drag(newPoint);
this.lastPoint = dragPoint;
return;
}
//if the bounds of the selected items is outside the bounds of the draggable area,
//recalculate the coordinates of the drag point to make sure the bounds of the selected items is inside the draggable area
if (this.DragAllowedArea.Left > newBounds.Left)
dragPoint = new Point(dragPoint.X - (newBounds.Left - this.DragAllowedArea.Left), dragPoint.Y);
else if (this.DragAllowedArea.Right < newBounds.Right)
dragPoint = new Point(dragPoint.X - (newBounds.Right - this.DragAllowedArea.Right), dragPoint.Y);
if (this.DragAllowedArea.Top > newBounds.Top)
dragPoint = new Point(dragPoint.X, dragPoint.Y - (newBounds.Top - this.DragAllowedArea.Top));
else if (this.DragAllowedArea.Bottom < newBounds.Bottom)
dragPoint = new Point(dragPoint.X, dragPoint.Y - (newBounds.Bottom - this.DragAllowedArea.Bottom));
}
else
{
//if the mouse position during a drag operation should be restricted within the DragAllowedArea
if (this.DragAllowedArea != Rect.Empty && !this.DragAllowedArea.Contains(newPoint))
{
//calculate the proper position of the dragPoint
double X = dragPoint.X;
double Y = dragPoint.Y;
if (X > this.DragAllowedArea.Right)
X = this.DragAllowedArea.Right;
else if (X < this.DragAllowedArea.Left)
X = this.DragAllowedArea.Left;
if (Y > this.DragAllowedArea.Bottom)
Y = this.DragAllowedArea.Bottom;
else if (Y < this.DragAllowedArea.Top)
Y = this.DragAllowedArea.Top;
dragPoint = new Point(X, Y);
}
}
}
//invoke the base implementation of the DraggingService Drag() method with the calculated proper coordinates of the dragPoint
base.Drag(dragPoint);
//update the lastPosition property to always keep track of the last drag position
this.lastPoint = dragPoint;
}
Public Overrides Sub Drag(ByVal newPoint As Point)
Dim dragPoint As Point = newPoint
If Me.IsOn Then
'if the actual bounds of the shape should be within the DragAllowedArea'
If Me.IsRestrictedToBounds Then
'get the bounds of the selected RadDiagramItems'
Dim selectionBounds = Me.GetSelectionBounds()
'find the drag offset by comparing the coordinates of the last and the new drag position '
Dim offset = New Vector(newPoint.X - Me.lastPoint.X, newPoint.Y - Me.lastPoint.Y)
'calculate the new bounds of the dragged selected items'
Dim newBounds = New Rect(selectionBounds.X + offset.X, selectionBounds.Y + offset.Y, selectionBounds.Width, selectionBounds.Height)
'if there is no predefined draggable area or '
'if the bounds of the dragged selected items are within the predefined draggable area'
'invoke the default implementation of the DraggingService Drag() method'
If Me.DragAllowedArea = Rect.Empty OrElse Me.DragAllowedArea.Contains(newBounds) Then
MyBase.Drag(newPoint)
Me.lastPoint = dragPoint
Return
End If
'if the bounds of the selected items is outside the bounds of the draggable area, '
'recalculate the coordinates of the drag point to make sure the bounds of the selected items is inside the draggable area '
If Me.DragAllowedArea.Left > newBounds.Left Then
dragPoint = New Point(dragPoint.X - (newBounds.Left - Me.DragAllowedArea.Left), dragPoint.Y)
ElseIf Me.DragAllowedArea.Right < newBounds.Right Then
dragPoint = New Point(dragPoint.X - (newBounds.Right - Me.DragAllowedArea.Right), dragPoint.Y)
End If
If Me.DragAllowedArea.Top > newBounds.Top Then
dragPoint = New Point(dragPoint.X, dragPoint.Y - (newBounds.Top - Me.DragAllowedArea.Top))
ElseIf Me.DragAllowedArea.Bottom < newBounds.Bottom Then
dragPoint = New Point(dragPoint.X, dragPoint.Y - (newBounds.Bottom - Me.DragAllowedArea.Bottom))
End If
Else
'if the mouse position during a drag operation should be restricted within the DragAllowedArea'
If Me.DragAllowedArea <> Rect.Empty AndAlso (Not Me.DragAllowedArea.Contains(newPoint)) Then
'calculate the proper position of the dragPoint'
Dim X As Double = dragPoint.X
Dim Y As Double = dragPoint.Y
If X > Me.DragAllowedArea.Right Then
X = Me.DragAllowedArea.Right
ElseIf X < Me.DragAllowedArea.Left Then
X = Me.DragAllowedArea.Left
End If
If Y > Me.DragAllowedArea.Bottom Then
Y = Me.DragAllowedArea.Bottom
ElseIf Y < Me.DragAllowedArea.Top Then
Y = Me.DragAllowedArea.Top
End If
dragPoint = New Point(X, Y)
End If
End If
End If
'invoke the base implementation of the DraggingService Drag() method with the calculated proper coordinates of the dragPoint '
MyBase.Drag(dragPoint)
'update the lastPosition property to always keep track of the last drag position'
Me.lastPoint = dragPoint
End Sub
We also need to make sure that the lastPoint property has the coordinates of the position where the drag was initiated. For that purpose we will also override the DraggingService InitializeDrag() method:
//override this method to get the coordinates of the point where the drag started
public override void InitializeDrag(Point point)
{
this.lastPoint = point;
base.InitializeDrag(point);
}
'override this method to get the coordinates of the point where the drag started'
Public Overrides Sub InitializeDrag(ByVal point As Point)
Me.lastPoint = point
MyBase.InitializeDrag(point)
End Sub
Finally, we need to configure the diagram to use our custom dragging implementation instead of the default DraggingService. This is why we need to create a new instance of the MyDragging class in the code-behind file of our view. Then we need to bind the properties defined within the custom dragging service to the view elements that control them:
private MyDragging newDraggingService;
public Example()
{
InitializeComponent();
this.InitializeNewServices();
}
private void InitializeNewServices()
{
//initialize MyDragging
this.newDraggingService = new MyDragging(this.diagram);
//create a binding with Path=IsOn
Binding binding = new Binding("IsOn");
//use the newDraggingService as a source of the binding
binding.Source = this.newDraggingService;
binding.Mode = BindingMode.TwoWay;
//apply the binding on the toggleDrag RadToggleButton
this.toggleDrag.SetBinding(RadToggleButton.IsCheckedProperty, binding);
//create a binding with Path=IsRestrictedToBounds
binding = new Binding("IsRestrictedToBounds");
//use the newDraggingService as a source of the binding
binding.Source = this.newDraggingService;
binding.Mode = BindingMode.TwoWay;
//apply the binding on the IsRestrictedToBounds RadToggleButton
this.IsRestrictedToBounds.SetBinding(RadToggleButton.IsCheckedProperty, binding);
//create a binding with Path=UseRotaitonBounds
binding = new Binding("UseRotaitonBounds");
//use the newDraggingService as a source of the binding
binding.Source = this.newDraggingService;
binding.Mode = BindingMode.TwoWay;
//apply the binding on the useRotaitonBounds RadToggleButton
this.useRotaitonBounds.SetBinding(RadToggleButton.IsCheckedProperty, binding);
}
Private newDraggingService As MyDragging
Public Sub New()
InitializeComponent()
Me.InitializeNewServices()
End Sub
Private Sub InitializeNewServices()
'initialize MyDragging '
Me.newDraggingService = New MyDragging(Me.diagram)
'create a binding with Path=IsOn'
Dim binding As New Binding("IsOn")
'use the newDraggingService as a source of the binding'
binding.Source = Me.newDraggingService
binding.Mode = BindingMode.TwoWay
'apply the binding on the toggleDrag RadToggleButton'
Me.toggleDrag.SetBinding(RadToggleButton.IsCheckedProperty, binding)
'create a binding with Path=IsRestrictedToBounds'
binding = New Binding("IsRestrictedToBounds")
'use the newDraggingService as a source of the binding'
binding.Source = Me.newDraggingService
binding.Mode = BindingMode.TwoWay
'apply the binding on the IsRestrictedToBounds RadToggleButton'
Me.IsRestrictedToBounds.SetBinding(RadToggleButton.IsCheckedProperty, binding)
'create a binding with Path=UseRotaitonBounds'
binding = New Binding("UseRotaitonBounds")
'use the newDraggingService as a source of the binding'
binding.Source = Me.newDraggingService
binding.Mode = BindingMode.TwoWay
'apply the binding on the useRotaitonBounds RadToggleButton'
Me.useRotaitonBounds.SetBinding(RadToggleButton.IsCheckedProperty, binding)
End Sub
And now we can use the newDraggingService instance and register it through the ServiceLocator:
public Example()
{
InitializeComponent();
this.InitializeNewServices();
this.diagram.ServiceLocator.Register<IDraggingService>(this.newDraggingService);
}
Public Sub New()
InitializeComponent()
Me.InitializeNewServices()
Me.diagram.ServiceLocator.Register(Of IDraggingService)(Me.newDraggingService)
End Sub
If you run the solution now, you should see the On button as checked which means that the mouse position during drag should always be within the blue rectangle indicating the draggable area. If you click on the IsRestrictedToBounds button, you will change the drag restrictions to use the shape bounds when identifying the available dragging positions of a shape. And as the UseRotatedBounds button is also checked the rotation bounds of the dragged shapes will also be taken into account while applying the drag restrictions.
You can further extend this example by updating the designated draggable area during pan and zoom operations. In order to do so, you can handle the RadDiagram ViewportChanged event:
<telerik:RadDiagram x:Name="diagram" ViewportChanged="OnDiagramViewportChanged">
<telerik:RadDiagramShape Geometry="{telerik:FlowChartShape ShapeType=BeginLoopShape}" Position="400 300" />
<telerik:RadDiagramShape Geometry="{telerik:FlowChartShape ShapeType=ExternalDataShape}" Position="500 400" />
</telerik:RadDiagram>
private void SetRestrictRect(Rect rect)
{
if (this.newDraggingService != null)
this.newDraggingService.DragAllowedArea = rect.InflateRect(-rect.Width / 4, -rect.Height / 4);
}
private void OnDiagramViewportChanged(object sender, PropertyEventArgs<Rect> e)
{
this.SetRestrictRect(e.NewValue);
this.border.Width = (e.NewValue.Width / 2) * this.diagram.Zoom;
this.border.Height = (e.NewValue.Height / 2) * this.diagram.Zoom;
}
Private Sub SetRestrictRect(ByVal rect As Rect)
If Me.newDraggingService IsNot Nothing Then
Me.newDraggingService.DragAllowedArea = rect.InflateRect(-rect.Width \ 4, -rect.Height \ 4)
End If
End Sub
Private Sub OnDiagramViewportChanged(ByVal sender As Object, ByVal e As PropertyEventArgs(Of Rect))
Me.SetRestrictRect(e.NewValue)
Me.border.Width = (e.NewValue.Width / 2) * Me.diagram.Zoom
Me.border.Height = (e.NewValue.Height / 2) * Me.diagram.Zoom
End Sub
Find a runnable project of the previous example in the WPF Samples GitHub repository.