LoginSignup
1
5

More than 1 year has passed since last update.

【WPF】Behaviorの実装方法【MVVM】

Last updated at Posted at 2022-03-27

Behaviorを実装してみる

WPFのBehaviorってなんかやること多いしXaml側には<i:Interactivity>~... みたいなよくわからん名前空間がネストしてあるしで何となく敬遠していたのでちゃんと調べました。

あとMVVM的に書きたいけどマウスイベントトリガーでアクションさせたい時どうすればいいのかわからなかったので
チートシート的にまとめました。
世はコードビハインドの記事で溢れかえっている🤕

やりたいこと - 左クリックした時に座標を取得

  1. Viewでのイベントを検知してViewModelで何かしたい(今回はCanvas上での左クリック)
  2. Viewのコントロールがもつ値をViewModelに渡したい(今回は左クリックした座標)

自分のチートシート用に一枚にまとめました。
image.png
こうなる↓
2022-03-28_05h07_36.gif

コード

CanvasDrawing.xaml
<UserControl x:Class="DrawRectangle.Views.CanvasDrawing"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:DrawRectangle.ViewModels" 
             xmlns:i="http://schemas.microsoft.com/xaml/behaviors" 
             xmlns:behaviors="clr-namespace:DrawRectangle.Behaviors"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">

    <UserControl.DataContext>
       <local:CanvasDrawingViewModel/>
    </UserControl.DataContext>

    <Grid>
        <TextBlock Name="Text1" 
                   HorizontalAlignment="Left" 
                   Margin="10,10,0,0" 
                   TextWrapping="Wrap"
                   Text="{Binding Text.Value}"
                   VerticalAlignment="Top"
                   Width="200"/>

        <Canvas Name="Canvas1"
                Background="#01010101" 
                Margin="0,37,0,0" >
                <i:Interaction.Behaviors>
                    <behaviors:MouseButtonBehavior MouseLeftButtonClicked="{Binding ClickLeftCommand}"/>
                </i:Interaction.Behaviors>
        </Canvas>
    </Grid>
</UserControl>

CanvasDrawingViewModel.cs
using Reactive.Bindings;
using System.Windows;

namespace DrawRectangle.ViewModels
{
    public class CanvasDrawingViewModel
    {
        public ReactivePropertySlim<string> Text { get; } = new ReactivePropertySlim<string>("クリックされていないな...");

        public ReactiveCommand<Point> ClickLeftCommand { get; } = new ReactiveCommand<Point>();

        public CanvasDrawingViewModel()
        {
            ClickLeftCommand.WithSubscribe(p => OnClickLeft(p));
        }

        private void OnClickLeft(Point p)
        {

            Text.Value = $"左クリックされたよ! X: {p.X} Y: {p.Y}";
        }
    }
}
MouseButtonBehavior.cs
using System.Windows;
using System.Windows.Input;
using Microsoft.Xaml.Behaviors;

namespace DrawRectangle.Behaviors
{
    public class MouseButtonBehavior : Behavior<FrameworkElement>
    {
        public static readonly DependencyProperty MouseLeftButtonClickedProperty =
            DependencyProperty.Register(
                nameof(MouseLeftButtonClicked),
                typeof(ICommand),
                typeof(MouseButtonBehavior),
                new FrameworkPropertyMetadata());

        public ICommand MouseLeftButtonClicked
        {
            get => (ICommand) GetValue(MouseLeftButtonClickedProperty);
            set => SetValue(MouseLeftButtonClickedProperty, value);
        }

        protected override void OnAttached()
        {
            AssociatedObject.MouseLeftButtonDown += AssociatedObjectOnMouseLeftButtonClicked;
        }

        private void AssociatedObjectOnMouseLeftButtonClicked(object sender, MouseEventArgs e)
        {
            AssociatedObject.CaptureMouse();
            var prevPoint = e.GetPosition(AssociatedObject);
            var point = new Point(prevPoint.X, prevPoint.Y);

            if (MouseLeftButtonClicked == null || !MouseLeftButtonClicked.CanExecute(point)) return;
            MouseLeftButtonClicked.Execute(point);

        }
    }
}

おまけ

ネットでBehaviorについて検索しているとSystem.Window.InteractivityMicrosoft.Xaml.Behaviorという名前空間が出てきてどう違うんだろうかと思っていましたが、どうもInteractivityをOSS化したのがXaml.Behaviorみたいです。

1
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
5