MouseDragElementBehavior を使うと簡単に実装する事ができます。

MouseDragElementBehavior が無い
Visual Studio 2019 から Behavior が 標準搭載されなくなりました。
なので、NuGet パッケージ から入れる必要があります。
プロジェクトに「Microsoft.Xaml.Behaviors.Wpf」パッケージを入れます。

MainWindow
MainWindow.xaml
<Window
<!-- 省略 -->
>
<Grid x:Name="LayoutRoot">
<Button Content="図形追加"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Width="120"
Style="{StaticResource MaterialDesignRaisedButton}"
Margin="10,80,0,0"
Click="AddShape_Click"/>
</Grid>
</Window>
Grid コントロール にユーザーコントロールを追加するため、LayoutRoot という名前をつけました。こうする事でコードビハインドから参照することが出来ます。
MainWindow.xaml.cs
private void AddShape_Click(object sender, RoutedEventArgs e)
{
LayoutRoot.Children.Add(new ShapeObject(100, 150));
}
図形追加ボタンを押したら、Grid コントロール ShapeObject ユーザーコントロール を追加しています。引数で追加位置を指定できるようにしています。
ShapeObject ユーザーコントロール
ShapeObject ユーザーコントロール を作っていきます。
ShapeObject.xaml
<UserControl
<!-- 省略 -->
>
<b:Interaction.Behaviors>
<b:MouseDragElementBehavior
ConstrainToParentBounds="True"
X="{Binding XPosition, Mode=TwoWay}"
Y="{Binding YPosition, Mode=TwoWay}"/>
</b:Interaction.Behaviors>
<Grid>
<StackPanel>
<TextBlock TextWrapping="Wrap" Text="{Binding XPosition, StringFormat=X:{0}}"/>
<TextBlock TextWrapping="Wrap" Text="{Binding YPosition, StringFormat=Y:{0}}"/>
</StackPanel>
</Grid>
</UserControl>
UserControl に MouseDragElementBehavior を付けています。これだけで、ドラッグ移動させることが出来ます。
ConstrainToParentBounds を True にする事で、外に出なくなります。
表示位置を表示するために、ViewModel とバインドして TextBlock で表示しています。

ShapeObject.xaml.cs
using System.Windows;
using System.Windows.Controls;
namespace WpfApp1
{
public partial class ShapeObject : UserControl
{
public ShapeObject(double _XPosition, double _YPosition)
{
InitializeComponent();
DataContext = new ShapeObjectViewModel()
{
XPosition = _XPosition,
YPosition = _YPosition
};
HorizontalAlignment = HorizontalAlignment.Left;
VerticalAlignment = VerticalAlignment.Top;
Width = 100;
Height = 100;
}
}
}
初期化してます。
ShapeObjectViewModel.cs
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace WpfApp1 {
public class ShapeObjectViewModel : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "") {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public double XPosition {
get { return _XPosition; }
set {
if (value != _XPosition) {
_XPosition = value;
NotifyPropertyChanged("XPosition");
}
}
}
private double _XPosition;
public double YPosition {
get { return _YPosition; }
set {
if (value != _YPosition) {
_YPosition = value;
NotifyPropertyChanged("YPosition");
}
}
}
private double _YPosition;
}
}
ドラッグ移動で 表示位置が変わったら 通知されるようにしています。
手順が面倒くさいです。