【WPF】マウスドラッグで動く PathGeometry を作る

Uncategorized
407 words

こんなのです。

環境

  • Visual Studio 2019
  • Microsoft.Xaml.Behaviors.Wpf (NuGet)

XAML

XAML に PathGeometry と ドラッグ移動用の四角を2つ置きます。

そして、ドラッグ移動用の四角にはそれぞれ MouseDragElementBehavior を付けてドラッグ移動できるようにしておきます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<Grid x:Name="LayoutRoot">
<Path Stroke="Crimson" StrokeThickness="3" x:Name="path">
<Path.Data>
<PathGeometry>
<PathFigure StartPoint="0,0">
<BezierSegment Point1="0, 0" Point2="0, 0" Point3="0, 0"/>
</PathFigure>
</PathGeometry>
</Path.Data>
</Path>
<Path Fill="LightPink"
x:Name="StartPosition"
Stretch="Fill"
HorizontalAlignment="Left"
Width="10"
Height="10"
VerticalAlignment="Top">
<Path.Data>
<RectangleGeometry Rect="0,0,10,10" RadiusX="3" RadiusY="3" />
</Path.Data>
<b:Interaction.Behaviors>
<b:MouseDragElementBehavior />
</b:Interaction.Behaviors>
</Path>
<Path Fill="LightBlue"
x:Name="EndPosition"
Stretch="Fill"
HorizontalAlignment="Left"
Width="10"
Height="10"
VerticalAlignment="Top">
<Path.Data>
<RectangleGeometry Rect="0,0,10,10" RadiusX="3" RadiusY="3" />
</Path.Data>
<b:Interaction.Behaviors>
<b:MouseDragElementBehavior />
</b:Interaction.Behaviors>
</Path>
</Grid>

コードビハインド

ドラッグ移動用の四角をドラッグ移動した時に PathGeometry を再描画するようにします。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public MainWindow()
{
InitializeComponent();
// 開始位置のドラッグイベント設定.
var startPositionBehaviors = Interaction.GetBehaviors(StartPosition);
var startPositionBehavior = (MouseDragElementBehavior)startPositionBehaviors.First();
startPositionBehavior.Dragging += StartPositionBehavior_Dragging;
// 終了位置のドラッグイベント設定.
var endPositionBehaviors = Interaction.GetBehaviors(EndPosition);
var endPositionBehavior = (MouseDragElementBehavior)endPositionBehaviors.First();
endPositionBehavior.Dragging += EndPositionBehavior_Dragging;
}
// 開始位置のドラッグイベント
private void StartPositionBehavior_Dragging(object sender, MouseEventArgs e)
{
var mouseDragElementBehavior = (MouseDragElementBehavior)sender;
var pathFigure = ((PathGeometry)path.Data).Figures.First();
var bezierSegment = (BezierSegment)pathFigure.Segments.First();
var startPosition = (Path)LayoutRoot.FindName("StartPosition");
// PathGeometry 再描画.
setPoint(
pathFigure,
new Point(
mouseDragElementBehavior.X + (startPosition.Width / 2),
mouseDragElementBehavior.Y + (startPosition.Height / 2)),
bezierSegment.Point3
);
}
// 終了位置のドラッグイベント
private void EndPositionBehavior_Dragging(object sender, MouseEventArgs e)
{
var mouseDragElementBehavior = (MouseDragElementBehavior)sender;
var pathFigure = ((PathGeometry)path.Data).Figures.First();
var endPosition = (Path)LayoutRoot.FindName("EndPosition");
// PathGeometry 再描画.
setPoint(
pathFigure,
pathFigure.StartPoint,
new Point(
mouseDragElementBehavior.X + (endPosition.Width / 2),
mouseDragElementBehavior.Y + (endPosition.Height / 2))
);
}

PathGeometry 再描画処理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private void setPoint(PathFigure pathFigure, Point startPoint, Point endPoint)
{
var width = Math.Abs(endPoint.X - startPoint.X);
var height = Math.Abs(endPoint.Y - startPoint.Y);
var point1 = new Point(startPoint.X - (width / 2), startPoint.Y + (height / 2));
var point2 = new Point(endPoint.X + (width / 2), endPoint.Y - (height / 2));
// 開始位置の中間ポイント設定.
point1.X = startPoint.X - (width / 2);
point1.Y = startPoint.Y;
// 終了位置の中間ポイント設定.
point2.X = endPoint.X + (width / 2);
point2.Y = endPoint.Y;
// 全ポイント設定.
var bezierSegment = (BezierSegment)pathFigure.Segments.First();
pathFigure.StartPoint = startPoint;
bezierSegment.Point1 = point1;
bezierSegment.Point2 = point2;
bezierSegment.Point3 = endPoint;
}