🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

MVVM

MVVM(Model View ViewModel)は構築上のデザインパターンで、表現ロジック(ViewModel)によってデータ(Model)からページ(View)を分離させます。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

Q&A

解決済

2回答

10179閲覧

ViewModelでイベントハンドラーを記述したい。あるいはPrism的なイベントハンドラー記述方法を知りたい

Arks

総合スコア8

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

MVVM

MVVM(Model View ViewModel)は構築上のデザインパターンで、表現ロジック(ViewModel)によってデータ(Model)からページ(View)を分離させます。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

0グッド

3クリップ

投稿2019/10/06 06:26

開発環境

C#でWPFアプリケーションを作成中
Visual Studio 2019
使用しているMVVMパッケージ Prism

質問のポイント

Prismらしいイベントハンドラーの記述方法が知りたい。特にsenderなどの情報を利用するためのDelegateCommand宣言方法を知りたい。

前提:知っている情報(イベントハンドラー)

コードビハインドにイベントハンドラーの本体を書き、XAMLでEventSetterを使えばイベントを作れることを確認しました。しかし、これはあまりPrism的ではないのではないかとなんとなく感じています。コードビハインドの記述が増えるのも気になります。コードビハインドに記述することなくsenderやeの情報を利用したいところなのですが・・・。

C#

1// View.xaml.cs 2private void TestEventHandler(object sender, MouseButtonEventArgs e) 3{ 4 Console.WriteLine("test"); 5 // senderやeの情報利用可能。 6}

XAML

1<!-- View.xaml --> 2<Page.Resources> 3 <Style TargetType="{x:Type DataGridRow}"> 4 <EventSetter Event="MouseLeftButtonUp" Handler="TestEventHandler"/> 5 </Style> 6</Page.Resources>

前提:知っている情報(Prismでのボタンクリックイベント)

DelegateCommandを使えばXAML側のCommandにメソッドをバインディングできることは知っています。

C#

1// ViewModel.cs 2private DelegateCommand clickEvent; 3public DelegateCommand ClickEvent => this.clickEvent ?? (this.clickEvent = new DelegateCommand(this.ExecuteClickEvent)); 4private void ExecuteClickEvent() 5{ 6 Console.WriteLine("test"); 7}

XAML

1<!-- View.xaml --> 2<Button Command="{Binding ClickEvent}"/>

本題:知りたい情報(ViewModelでイベントハンドラーを記述したい。あるいはPrism的なイベントハンドラー記述方法を知りたい)

下記は想像で作成したコードですが、例えばこのような方向性ですっきり書く方法はないのでしょうか?

C#

1// [注意]推測と想像で作成した動かないコード 2// ViewModel.cs 3private DelegateCommand(object sender, MouseButtonEventArgs e) eventHandler; 4public DelegateCommand(object sender, MouseButtonEventArgs e) ClickEvent => this.clickEvent ?? (this.clickEvent = new DelegateCommand(this.ExecuteClickEvent)); 5private void ExecuteClickEvent(object sender, MouseButtonEventArgs e) 6{ 7 Console.WriteLine("test"); 8 // senderやeの情報利用可能。 9}

XAML

1<!-- [注意]推測と想像で作成した動かないコード --> 2<!-- View.xaml --> 3<Page.Resources> 4 <Style TargetType="{x:Type DataGridRow}"> 5 <EventSetter Event="MouseLeftButtonUp" Handler="TestEventHandler"/> 6 <!-- 特に何も指定しなくてもViewModel.cs側でobjectとMouseButtonEventArgsが割り当てられる --> 7 </Style> 8</Page.Resources>

以上です。WPFとPrismを使ったことがある方の返信をいただけると幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gentaro

2019/10/06 06:33 編集

「すっきり」って何を指してるんだろう。Prismのコマンドをバインドする方法の何が「すっきり」してないのか説明しないと理解できないと思うけど。
Arks

2019/10/06 06:34

Prismの常識を詳しく知らないので「すっきり」していないものをそう称していることがあるとお考えください。より「すっきり」しているもの。「Prismならこう書くのが当然でしょう」といった発想があったら教えていただけると発想を修正することができます。もしPrismの常識をご存知でしたら書き方のヒントをいただけるととても助かります。
Arks

2019/10/06 06:55

MVVMの原則ではVMはVへの参照を必要としてはいけないようですが、となるとMはどうやってsenderなどの情報を利用するべきなのでしょう。senderなどの情報はVのコードビハインドのみで利用すべきということなのでしょうか。 InvokeCommandActionについても読み込んでみます。
gentaro

2019/10/06 07:20

どういう処理をやろうとしてるのかわかりませんが、MVVMを採用するからコードビハインド書いちゃだめという決まりはないので、必要ならViewのコードビハインドに書けばいいんじゃないでしょうか。 それをやりたくないなら、そもそもViewの要素に依存する設計を変更すればいいだけで、例えばバインドするコマンドそのものを別に用意すれば発生元ごとに処理は分けられると思いますけど。
Arks

2019/10/06 08:40

InvokeCommandActionを試しています。<i:interaction.Triggers>を使ってコマンドを呼び出すことができるというのはなんとなくわかりましたが、VM側のDelegateCommand定義がいまいちわかりません。senderとeをもたせたいところなのですが、たとえばDelegateCommand<MouseButtonEventArgs e>で定義すると「非ジェネリック 種類'DelegateCommand'は型引数と一緒には使用できません」エラーが発生します。DelegateCommand<MouseButtonEventArgs>として定義すればエラーはでないようですが、DelegateCommand<object, MouseButtonEventArgs>は「非ジェネリック~」エラーが起きます。 コピペで増やすタイプの類似記述は避けたほうが良いというのを聞いたことがあるので、必要な分だけバインドするコマンドを用意するというのはできれば回避したい気はしています。それと下記のケースだとあまり合わないかなと。 たとえばDataGridをクリックしたときにsenderを利用して、クリック直下にあるアイテムのプロパティなどを利用するシーンを思い描いています。senderやeは細かな情報を利用する上で重要かなと考えているのですが、普通senderはあまり利用しないものなのでしょうか。 parameter調べてみます。
Zuishin

2019/10/06 08:54

XAML で CommandParameter で指定したオブジェクトが parameter として渡されます。 <Button Command="{Binding ClickCommand}" CommandParameter="{Binding RelativeSource=...
guest

回答2

0

自己解決

頂いた情報を元に自己解決しました。

知りたかったことと答え

Prismらしいイベントハンドラーの記述方法が知りたい。特にsenderなどの情報を利用するためのDelegateCommand宣言方法を知りたい。

Prismらしいと思えるような記述が見つかりました。下に記載します。
DelegateCommandの宣言では1つだけパラメーターを持たせることができることがわかりました。senderとEventArgs両方を宣言して利用するということはできません。2つの情報を合わせて1つのobjectに見せかければ渡すことができなくはなさそうです。ただ、PrismのInvokeCommandActionではEventArgsだけを渡す仕組みになっているようです。これに従って工夫することにします。もしどうしても複数の値をメソッドに渡したい場合には「MultiBinding」「MarkupExtensionでBindを拡張する」といったヒントが役に立ちそうです。特にMarkupExtensionについてはここの解説がとても参考になりました。

PrismのInvokeCommandActionを利用した解決策

XAML

1<!-- View.xaml --> 2xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 3xmlns:prism="http://prismlibrary.com/" 4 5<TextBox> 6 <i:Interaction.Triggers> 7 <i:EventTrigger EventName="TextChanged"> 8 <prism:InvokeCommandAction Command="{Binding Command1}"/> 9 <!-- i:InvokeCommandActionも存在するが、そちらではEventArgsを渡せない --> 10 </i:EventTrigger> 11 </i:Interaction.Triggers> 12</TextBox>

C#

1// ViewModel.cs 2private DelegateCommand<EventArgs> command1; 3public DelegateCommand<EventArgs> Command1 => this.command1 ?? (this.command1 = new DelegateCommand<EventArgs>(this.ExecuteCommand1)); 4private void ExecuteCommand1(EventArgs e) 5{ 6 Console.WriteLine(e.ToString()); 7}

イベントハンドラーをVMで記述する方法を模索しましたが、CommandParameterでVMのメソッドに値を渡せることを知れたので、この手段を使って課題解決を図れるケースも多々あると感じています。アドバイスしていただきありがとうございました。

投稿2019/10/07 09:46

Arks

総合スコア8

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sakizakino

2024/02/07 02:08

今後こちらの情報を見た人のために一応書いておきます。 <prism:InvokeCommandAction Command="{Binding Command1}"/> では、こちらを設定しているTextBoxのIsEnabledのBindingが壊れます。 <i:InvokeCommandAction Command="{Binding Command1}" PassEventArgsToCommand="True"/> とすると、TextBoxのIsEnabledのBindingを壊さずにイベント引数をVMに渡せます。
guest

0

こちらのようですね。同じ事を調べていて助かりました。ありがとうございます。

投稿2019/10/27 13:00

編集2019/10/27 13:03
5REva

総合スコア15

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問