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

pathgeometry-mouse-drag-move アプリ開発

こんなのです。

環境

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

XAML

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

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

<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 を再描画するようにします。

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 再描画処理

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;
}
タイトルとURLをコピーしました