1

ビューモデルのインスタンスが複数あります。

<views:MyView x:Name="view1" mefed:ViewModelLocator.NonSharedViewModel="MyViewModel" />
<views:MyView x:Name="view2" mefed:ViewModelLocator.NonSharedViewModel="MyViewModel" />

これら 2 つのインスタンスは、異なるメッセージをリッスンする必要があります。したがって、何らかの方法でこれらのビューモデル インスタンスにタグを付ける必要があります。どのように?

と を使用MEFedMVVMしてPrismいます。ビューモデルに何らかの状態を知らせる方法が必要です。例えば:

<views:MyView x:Name="view1" mefed:ViewModelLocator.NonSharedViewModel="MyViewModel">
  <!-- Let the viewmodel know it is of type X -->
</views:MyView>
<views:MyView x:Name="view2" mefed:ViewModelLocator.NonSharedViewModel="MyViewModel">
  <!-- Let the viewmodel know it is of type Y -->
</views:MyView>

これはどのように達成できますか?

理想的な世界では、XAML を介してビューのパラメーター化されたコンストラクターを使用しますが、これはサポートされていません。別のアイデアは、ビューに異なるクラスを使用することですが、すぐにコードが肥大化します!

4

1 に答える 1

2

簡単な回答と要約:

お気づきのように、本当に必要なのは XAML から ViewModel をパラメーター化することです。したがって、私の本能は、ViewModel のパラメーターを渡す機能を提供するためにAttached Behaviorを作成することです。より具体的には、(a)必要な ViewModel(b) その ViewModel のパラメーターの両方を指定できる単一のAttached Behavior クラスが必要であるということです。可能な限りDRYでありながら、単一のクラスでこれらの両方の欲求を満たすには、「ブレンド」動作を使用するのが最も簡単だと思います。なぜなら、ブレンド動作は静的クラスではないため、それらを使用できる方がはるかに簡単だと思われるからです。両方の関連情報を一緒に渡します。

説明:

最初の簡単な免責事項: MEFedMVVM や Prism を使用したことはありません (ただし、他の MVVM ライブラリを使用したことはあります)。したがって、このアプローチは、「通常の」方法 (つまり、DataContext を自動的に接続するなど) で物事を使用するときに Prism が提供する可能性のある「魔法の」ものに依存しないため、この考え方を組み立てましょう。

「通常の」アタッチされた動作と「ブレンド」動作の違いについての良い記事については、このブログ投稿が気に入っています。ここで彼の説明を繰り返すことはしませんが、私が気付いた重要なことは、通常の添付ビヘイビアーは、その機能を実行するために単一の情報 (つまり、単一の「パラメーター」) に依存しているように見えるということです。など(ブログ投稿から):

<GridView local:ItemClickNavBehavior.Destination="Home" ...>

これをあなたのケースに当てはめて、通常のAttached Bahaviorsを使用した場合にどのように機能するかを調べてみましょう。Attached Behavior クラスを作成し、それを「MyViewModel1Creator」と呼びます。 (1)「Type」という添付プロパティを登録し、 (2)「Type」の変更コールバック ハンドラーを含めます (初期設定時にも呼び出されます - リンクされたブログ投稿の「HookupBehavior」メソッドを参照してください)。この変更コールバックでは、「ViewModel1」をインスタンス化し、それに「Type」添付プロパティの値を渡します。また、このメソッドでは、ビューの DataContext の設定など、その他の必要事項を処理できます。コールバック ハンドラ (Dependency オブジェクト パラメータ)。

次に、「MyViewModel1Creator」クラスの Xaml の使用は次のようになります。

<views:MyView x:Name="view1" MyBehaviors:MyViewModel1Creator.Type="X" />
<views:MyView x:Name="view2" MyBehaviors:MyViewModel1Creator.Type="Y" />

これは機能しますが、このアプローチには欠点があります(通常の添付プロパティを使用)。このアプローチを使用するには、ViewModel ごとに個別の Attached Behavior クラスを作成する必要があります。つまり、3 つの ViewModel ("ViewModel1"、"ViewModel2"、"ViewModel3") がある場合は、3 つの Attached Behavior クラス ( "ViewModel1Creator"、"ViewModel2Creator"、"ViewModel3Creator")。それぞれがそれぞれの ViewModel をインスタンス化します (そして、上記のように "Type" 添付プロパティを公開します)。もう 1 つの欠点は、渡すパラメーターを 追加する方法を見つけるのが難しいように思われることです。

上記の方法とは少し異なるアプローチですが、 DRYであるという点では同様に不十分ですが、「CreateViewModel_1_WithType」のような名前の複数の添付プロパティを格納する単一のクラス (「MyViewModelCreator」と呼びます。今回は「1」は付けません) を使用します。 "、"CreateViewModel_2_WithType"、"CreateViewModel_3_WithType" など。使用方法は次のようになります。

<views:MyView x:Name="view1"
              MyBehaviors:MyViewModelCreator.CreateViewModel_1_WithType="X" />
<views:MyView x:Name="view2" 
              MyBehaviors:MyViewModelCreator.CreateViewModel_1_WithType="Y" />

繰り返しますが、これらのアプローチはあまり DRY ではないため、本当に必要なのは...

次に、 「ブレンド」動作を使用した場合にどのように機能するかを考えてみましょう:

型指定された Behavior から派生するクラスを作成します。ビューの場合はおそらく になるBehavior<UserControl>ため、クラスの見出しは次のようになります
public class ViewModelSetupBehavior : Behavior<UserControl>。このクラスでは、(1) "Type" 依存関係プロパティと "ViewModelName" 依存関係プロパティを含む、必要な数の依存関係プロパティを登録し、(2)OnAttached()どちらの ViewModel もインスタンス化するメソッドをオーバーライドします。「ViewModelName」依存プロパティの値によって示され、「Type」依存プロパティの値もそれに渡します。繰り返しますが、これは、ビューの DataContext の設定など、その他の必要性も処理する場所になります。ビヘイビアーが「アタッチされている」オブジェクトにアクセスできます。AssociatedObject財産。

これにより、次のことが可能になります。

<views:MyView x:Name="view1">
    <i:Interaction.Behaviors>
        <MyBehaviors:ViewModelSetupBehavior ViewModelName="ViewModel1" Type="X" SomeOtherParam="bla" />
    </i:Interaction.Behaviors>
</views:MyView>

<views:MyView x:Name="view2">
    <i:Interaction.Behaviors>
        <MyBehaviors:ViewModelSetupBehavior ViewModelName="ViewModel1" Type="Y" />
    </i:Interaction.Behaviors>
</views:MyView>

ここで、単一のBehavior クラスを使用してすべての ViewModel を作成できることに注意してください。いくつかのパラメーターを渡して、ViewModel をインスタンス化する方法を指定できます。

于 2013-01-24T16:53:20.820 に答える