For main answer. I found a non-strictly binding way to fix it.
We just need to add a DependencyProperty
for position to the DraggableContentControl
.
public static readonly DependencyProperty PositionProperty =
DependencyProperty.Register("Position", typeof(Point), typeof(DraggableContentControl), new PropertyMetadata(OnPositionPropertyChanged));
public Point Position
{
get { return (Point)GetValue(PositionProperty); }
set { SetValue(PositionProperty, value); }
}
private static void OnPositionPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
DraggableContentControl control = d as DraggableContentControl;
Point newValue = (Point)e.NewValue;
Canvas.SetLeft(control, newValue.X);
Canvas.SetTop(control, newValue.Y);
}
Further, we can simplify the method Drag_OnMouseMove
to the following form:
private void Drag_OnMouseMove(object sender, MouseEventArgs e)
{
if (!this.IsDragActive)
{
return;
}
Point currentPosition = e.GetPosition(this.ParentInputElement);
currentPosition.Offset(-this.DragOffset.X, -this.DragOffset.Y);
Position = currentPosition;
}
And now we bind to the Position property instead of the Canvas.Left/Top properties:
<controls:ItemsCanvas.ItemContainerStyle>
<Style TargetType="controls:DraggableContentControl">
<Setter Property="Position" Value="{Binding Position, Mode=TwoWay}"/>
</Style>
</controls:ItemsCanvas.ItemContainerStyle>
Now, when we change the position from the viewmodel, our content control changes its position on the canvas, and when we change the position with the mouse, the viewmodel's position is updated as well.
At least, without this, I could change the position only through viewmodel, but nothing worked through Canvas.SetLeft/SetTop