MVVM とステートフル コマンド - 良いアイデアか悪いアイデアか?

StackOverflow https://stackoverflow.com/questions/1324309

  •  19-09-2019
  •  | 
  •  

質問

MVVM の専門知識を持つ誰かが、次のことが良いアイデアかどうかについて意見を提供できることを期待して、ここに投稿しようと思いました。

私は Sacha Barber の Cinch MVVM フレームワークを使用しています。これには Marlon Grech の SimpleCommand クラスが含まれています。

このクラスになく、他の代替クラスにはないものの 1 つは Text プロパティです。これは、UI 要素をコマンド操作の「タイトル」にバインドするためによく使用されます。その結果、私は Text プロパティを公開するこのクラスの拡張機能を作成しました。

さて、私が遭遇したのは、コマンドを使用してデバイスへの接続を切り替えるユースケースです。これを実装するにはさまざまな方法があります (常にあるわけではありません - ソフトウェアです!)。1 つの方法は、ViewModel から複数のコマンド オブジェクト (「切断」用と「接続」用) を公開することです。ビュー モデルに接続状態 (IsConnected) を示すプロパティを公開させ、ビューを Connect コマンドまたは Disconnect コマンドのいずれかに条件付きでバインドさせます。しかし、このオプションに対する私の反応は...やったー!

代わりに私が最初に検討し始めたのは、Text プロパティを提供するだけでなく、コマンド オブジェクトに INotifyPropertyChanged を実装させ、システム状態に応じてビューモデルによってテキスト プロパティを「接続」または「切断」に動的に変更できるようにすることでした。こうすることで、複数のコマンドを使用することを避け、単一の「ToggleConnection」コマンド オブジェクトだけを公開することができます。

ただし、この道をたどり始めると、コマンドの状態に応じて UI を変更する必要がある、このパターンの他のバリエーションがある可能性があることに気づきました。たとえば、接続状態に応じてコマンドのテキストを変更するだけでなく、接続状態に応じてアイコンを変更する必要がある場所がある場合があります。そこで、INotifyPropertyChanged を実装し、「Text」と「State」という 2 つのプロパティを公開する「Stateful」クラスの作成を開始しました。State のタイプをユーザーが定義できるようにクラスをジェネリックにしました (私は通常、回避可能な場合には 'object' を使用しないことを好みます)。

私の質問は...これは良い考えだと思いますか、それとも悪い考えだと思いますか?コマンドの本来の意図や設計から逸脱している可能性があります。私が見たところによると、コマンド オブジェクトはシステムの「動詞」であるため、ステートレスであることが一般的に意図されているのかもしれません。ルーティングされたコマンドでは、私が正しく理解していれば、通常はコマンドのターゲットのみが状態を持つと予想されます。特に、コマンド バインディングが宣言されている場所に応じて、同じコマンドが異なるハンドラーにルーティングされる可能性があるためです。

したがって、少なくともルーティングされたコマンドでは、状態は意味をなさないのではないかと考えています。

ただし、私はルーティングされたコマンドを扱っているのではなく、特に MVVM コマンドを扱っています。この場合、基本的にコマンドの条件付きルーティングはありません。MVVM ビューは特定のビューモデルのコマンド オブジェクトに直接バインドされ、ハンドラーを実行して実行できます。

この場合、意味はあるのでしょうか?

役立つ/興味深い場合に備えて、問題のコードのコピーを添付しました。

ありがとう、フィル

役に立ちましたか?

解決

どちらが作業しやすいと思うかはあなた次第です。

私は個人的に、コマンドに .Text プロパティを追加しません。単にこれらのコマンドを再利用できないからです。フレームワークで提供される RoutedUICommands (または同様のカスタム静的コマンド) とは異なります。これらはどこでも再利用され、そのコマンドで「Exit」の翻訳が変更された場合、アプリケーション全体に反映されるためです。これはあなたの例には当てはまりません - すべてが 1 回限りになります。

あなたの場合、ボタンテキストのこのテキストは実際にはコマンドから分離されているため(一方が他方に影響を及ぼしているとしても)、おそらく最終的にはそれらを分離するのがより簡単になり、コードが少し少なくなるでしょうが、違いはありません。それは、最終的には何よりも好みの問題になるでしょう。

2 つのコマンドについては、私も間違いなくあなたに賛成です。あなたが作成するほとんどのボタンデリゲートは、何らかの方法で状態に反応する必要があります(通信するサービスがダウンしている、ユーザーがこれを選択した場合はこのデータをこの方法で入力する必要がある、など)。そのため、次のようにすることが間違っているとは思いませんデリゲートは ViewModel 上のステートフルな情報に適応します。

それにしても、ちょっと言葉が荒いですね…重要なのは、「快適だと思うことは何でもする」ということです。

他のヒント

最後の投稿者が言ったように、「心地よいものなら何でも」。

私の場合、通常は次のようなものを使用します デリゲートコマンド. 。何らかのデータにバインドする必要がある場合は、VM にバインドします。コマンドが実行されると、(init 時に DelegateCommand に提供されたデリゲートを介して) VM 内で実行されます。その後、実行されたデリゲートは、コマンドを満たすために再利用可能なコードを実行する場合と実行しない場合があります。

コマンドを独自の VM として使用したいようですね。これまで自分でこれをやろうと思ったことはありませんでしたが、気分が良いなら、ぜひやってみてください。:)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top