WPFで図形をマウスに追従させる
作るもの
作り方
適当な図形を作る
<Rectangle Stroke="Green"
StrokeThickness="5"
Width="50"
Height="50">
</Rectangle>
RenderTransformにTranslateTransformオブジェクトをセット
WPFではコントロールの座標を指定することはできないので、UIElementクラスにあるRenderTransformプロパティに、図形の変形情報を表すTranslateTransformオブジェクトを格納します。
<Rectangle Stroke="Green"
StrokeThickness="5"
Width="50"
Height="50">
<Rectangle.RenderTransform>
<TranslateTransform X="{Binding X.Value}"
Y="{Binding Y.Value}"/>
</Rectangle.RenderTransform>
</Rectangle>
ViewModelを作ってバインド
TranslateTransformクラスのXYに移動量を入れます。
バインドしたいのですごく簡単なViewModelを作ります。
class MainWindowViewModel
{
public ReactivePropertySlim<double> X { get; } = new ReactivePropertySlim<double>();
public ReactivePropertySlim<double> Y { get; } = new ReactivePropertySlim<double>();
}
バインドします。
<Rectangle Stroke="Green"
StrokeThickness="5"
Width="50"
Height="50">
<Rectangle.RenderTransform>
<TransformGroup>
<TranslateTransform X="{Binding X.Value}"
Y="{Binding Y.Value}"/>
</TransformGroup>
</Rectangle.RenderTransform>
</Rectangle>
ViewModelのX, Yをいじる
あとはViewModelのX,Yをいじれば図形が動きます。
コードビハインドを汚す場合
コードビハインドを使ってもいいなら簡単です。
WindowのMouseMoveイベントで座標を取得してVMに直接代入すればいいです。
public partial class MainWindow : Window
{
public MainWindow() {
InitializeComponent();
}
private MainWindowViewModel VM => (MainWindowViewModel)DataContext;
private void Window_MouseMove(object sender, MouseEventArgs e) {
var mousepos = e.GetPosition(this);
VM.X.Value = mousepos.X;
VM.Y.Value = mousepos.Y;
}
}
<Window x:Class="MouseTrackShape.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MouseTrackShape"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800"
MouseMove="Window_MouseMove">
<Window.DataContext>
<local:MainWindowViewModel/>
</Window.DataContext>
<Grid>
<Rectangle Stroke="Green"
StrokeThickness="5"
Width="50"
Height="50">
<Rectangle.RenderTransform>
<TransformGroup>
<TranslateTransform X="{Binding X.Value}"
Y="{Binding Y.Value}"/>
</TransformGroup>
</Rectangle.RenderTransform>
</Rectangle>
</Grid>
</Window>
しかし、実はこのままだとおかじな動きになります。
これは、TranslateTransformが初期位置からの移動量を指定するオブジェクトだからですね。
これを回避するために図形の初期位置を左上にしておきます。
<!--略-->
<Rectangle Stroke="Green"
StrokeThickness="5"
Width="50"
Height="50"
HorizontalAlignment="Left"
VerticalAlignment="Top">
<!--略-->
ちゃんとマウスに追従するようになりました。
コードビハインドを汚さない場合
コードビハインドを汚さずにやるなら少し大変です。
ビヘイビアを使うので、System.Windows.Interactivityを持っていない人はnugetからインストールしてください。
次のようなビヘイビアを作成します。
public class MouseBehaviour : System.Windows.Interactivity.Behavior<FrameworkElement>
{
public static readonly DependencyProperty MouseYProperty = DependencyProperty.Register(
"MouseY", typeof(double), typeof(MouseBehaviour), new PropertyMetadata(default(double)));
public double MouseY {
get { return (double)GetValue(MouseYProperty); }
set { SetValue(MouseYProperty, value); }
}
public static readonly DependencyProperty MouseXProperty = DependencyProperty.Register(
"MouseX", typeof(double), typeof(MouseBehaviour), new PropertyMetadata(default(double)));
public double MouseX {
get { return (double)GetValue(MouseXProperty); }
set { SetValue(MouseXProperty, value); }
}
protected override void OnAttached() {
AssociatedObject.MouseMove += AssociatedObjectOnMouseMove;
}
private void AssociatedObjectOnMouseMove(object sender, MouseEventArgs mouseEventArgs) {
var pos = mouseEventArgs.GetPosition(AssociatedObject);
MouseX = pos.X;
MouseY = pos.Y;
}
protected override void OnDetaching() {
AssociatedObject.MouseMove -= AssociatedObjectOnMouseMove;
}
}
このコードは以下サイトから拝借しました。
https://stackoverflow.com/questions/30047415/how-do-i-get-mouse-positions-in-my-view-model
このビヘイビアは割り当てられたコントロールのMouseMoveイベントを購読して、そのXY座標をMouseX, MouseY依存関係プロパティに格納するものです。
そしてWindowにこのビヘイビアを割り当てて、ViewModelのX, YとビヘイビアのMouseX, MouseYとバインドすればOKですね。
<Window x:Class="MouseTrackShape.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MouseTrackShape"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<local:MouseEventArgsToPositionConverter x:Key="MouseEventArgsToPositionConverter"/>
</Window.Resources>
<Window.DataContext>
<local:MainWindowViewModel/>
</Window.DataContext>
<Grid>
<Rectangle Stroke="Green"
StrokeThickness="5"
Width="50"
Height="50"
HorizontalAlignment="Left"
VerticalAlignment="Top">
<Rectangle.RenderTransform>
<TranslateTransform X="{Binding X.Value}"
Y="{Binding Y.Value}"/>
</Rectangle.RenderTransform>
</Rectangle>
</Grid>
<i:Interaction.Behaviors>
<local:MouseBehaviour MouseX="{Binding X.Value, Mode=OneWayToSource}" MouseY="{Binding Y.Value, Mode=OneWayToSource}" />
</i:Interaction.Behaviors>
</Window>
さいごに
以上です。
RenderTransformプロパティはUIElementクラスにあるので、図形だけじゃなくて例えばボタンなんかをマウスに追従させることもできますよ。
使いみちは謎ですが…
Author And Source
この問題について(WPFで図形をマウスに追従させる), 我々は、より多くの情報をここで見つけました https://qiita.com/yutorisan/items/8cf4c11d4f5809749fbb著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .