LoginSignup
3
4

More than 3 years have passed since last update.

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

Last updated at Posted at 2019-06-24

やりたいこと

以前の記事で、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のメソッドの呼び方1 -->
                    <i:InvokeCommandAction Command="{Binding func}"/>
                    <!-- ViewModelのメソッドの呼び方2(ViewModelの中のメソッドを呼ぶ) -->
                    <ei:CallMethodAction TargetObject="{Binding}" MethodName="EventFunc"/>
                    <!-- ViewModelのメソッドの呼び方3(コードビハインドの中のメソッドを呼ぶ) -->
                    <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のメソッドの呼び方3(コードビハインドの中のメソッドを呼ぶ)」のところ。

<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のプロパティが変わった時に、コードビハインドのメソッドを呼べる、とかの方が、真価なのかもしれない。

コード

関連記事

[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

3
4
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
3
4