[C#/WPF]ビューモデルからビューのメソッドを呼ぶ代わりに、EventTriggerでMouseDown等のイベントを拾ってビューのメソッドを呼ぶ

# やりたいこと
[以前の記事](https://qiita.com/tera1707/items/158db72db21b17a1d9c5)で、View(コードビハインド)でしかできないことがあるので、コードビハインドに書いたメソッドを、ViewModelから呼ぶ、ということを実験した。

ViewModelのタイミングで(例えば、ボタンを押したときにプロパティの値をif分で判定して、条件を満たすときだけ)Viewのメソッドを呼ぶ、とかだと以前の記事のやり方をしないといけなさそうだが、だた単純に**「ボタンを押されたときにViewのメソッドを呼びたい」**という場合なら、もっと簡易的に簡単にできる方法を思いついたので備忘メモする。

# やり方

下記を使う。

- Interaction.Triggers
- EventTrigger
- CallMethodAction

やることとしては、

- Interaction.TriggersとEventTriggerで何をトリガーにするか決めて
- CallMethodActionでコードビハインドに書いたメソッドを呼ぶ

だけ。

# サンプルコード

```MainWindow.xaml
<Window x:Class="WpfApp1.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:i="http://schemas.microsoft.com/expression/2010/interactivity" 
        xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800"
        Name="Root">
    <Grid>
        <TextBlock Margin="40" Background="Yellow">この黄色いTextBlockを押すと、トリガーが発火します
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="MouseDown">
                    <!-- ViewModelのメソッドの呼び方１ -->
                    <i:InvokeCommandAction Command="{Binding func}"/>
                    <!-- ViewModelのメソッドの呼び方２(ViewModelの中のメソッドを呼ぶ) -->
                    <ei:CallMethodAction TargetObject="{Binding}" MethodName="EventFunc"/>
                    <!-- ViewModelのメソッドの呼び方３(コードビハインドの中のメソッドを呼ぶ) -->
                    <ei:CallMethodAction TargetObject="{Binding ElementName=Root}" MethodName="CodeBehindFunc"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </TextBlock>
    </Grid>
</Window>
```

```MainWindow.xaml.cs
using System.Windows;

namespace WpfApp1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new ViewModel();
        }

        public void CodeBehindFunc()
        {
            MessageBox.Show("CallMethodAction でトリガー発火(コードビハインドのメソッド)");
        }
    }
}
```

```ViewModel.cs
using System.Windows;
using System.Windows.Input;

namespace WpfApp1
{
    class ViewModel
    {
        public ICommand func { get; set; }

        public ViewModel()
        {
            func = new DelegateCommand(
                () =>
                {
                    MessageBox.Show("トリガー発火");
                    return;
                });
        }

        public void EventFunc()
        {
            MessageBox.Show("CallMethodAction でトリガー発火(ViewModelのメソッド)");
        }
    }
}
```

# 説明
今回やりたかったのが、MainWindow.xamlの中の「ViewModelのメソッドの呼び方３(コードビハインドの中のメソッドを呼ぶ)」のところ。

`<i:EventTrigger EventName="MouseDown">`で、TextBlockでマウスが押されたときに、コードビハインドに書かれたメソッド「CodeBehindFunc」を呼んでいる。

この書き方であれば、「EventTrigger」で表現できるイベントであれば、「ViewModelのICommand」「ViewModelクラスのメソッド」「コードビハインドのメソッド」のどれでも呼べる。

EventTriggerのEventNameを変えてやれば、クリックしたときだけでなく、表示時に一回なにかする、とかもできる。

また、サンプルのように、`<i:EventTrigger EventName="MouseDown">`の中に書いたTriggerActionを継承したクラスのオブジェクト(CallMethodActionやInvokeCommandActionなど)をセットしてやれば、上から順番に実行してくれるので、ViewModelのICommandとコードビハインドのメソッドの両方を実行するとかもできそう。(それが良いかどうかは別問題)

# 備考
書き終わってから、「コントロールのイベントハンドラを追加して、そこに処理を書けばこんなことしなくて済むのでは？」と思ってしまった。

もしかすると、`i:EventTrigger `よりも、`PropertyChangedEventTrigger`を使って、ViewModelのプロパティが変わった時に、コードビハインドのメソッドを呼べる、とかの方が、真価なのかもしれない。

# コード
https://github.com/tera1707/WPF-/tree/master/003_EventTrigger2

# 関連記事
[C#/WPF]ビューモデルからビューのメソッドを呼ぶ
https://qiita.com/tera1707/items/158db72db21b17a1d9c5

【C#/WPF】EventTriggerを使って、Buttonでなくてもクリック時のCommandをかけるようにする
https://qiita.com/tera1707/items/7ecde6e97a19437cbf72

# 参考
WPF4.5入門 その58「Behavior」
https://blog.okazuki.jp/entry/2014/12/21/205558