0

シナリオ: ユーザーから送信されたフィードバックを受け取る Web サービスがあります。Feedbackクラスにはユーザーがいます。ViewModel では、ユーザーから送信されたフィードバックの完全なリストを取得し、ビューでそれにバインドします。リスト内のユーザーにバインドして、そのフィードバックの送信者を表示します。ここでは珍しいことは何もありません。ただし、ユーザーにいくつかのコントロールを追加して、クリックするといくつかのアクションが実行されるようにし、このコントロールをアプリのいくつかの場所で使用したいと考えています。

問題:適切なアクションでUserViewandを作成する必要があることは明らかです。しかし、クラスUserViewModel内のユーザーをに置き換えるにはどうすればよいですか? または、他の推奨される方法はありますか ( を に返すコンバーターを作成するなど) ?FeedbackViewModelUserViewModelContentPresenter

私は、MIX10 での「Build Your Own MVVM Framework」の講演に基づいたカスタム MVVM フレームワークを使用しています (これは、MVVM について詳しく学び、フレームワークをシンプルかつ高速に保つための演習として行っているためです)。

4

2 に答える 2

1

Caliburn.Micro はその MIX10 トークの最終結果であり ContentControl、解決されたビューとビューモデルに s を自動的にバインドします

同じアプローチに従うことができます:

子VMを親VMのプロパティにします...(誰かがすでに回答しているように)

public class UserViewModel 
{
    public User User { get; set; }
}

public class FeedbackViewModel 
{ 
    public UserViewModel UserView { get; set; }
}

次にContentControl、子 VM を親ビューに挿入できるようにするために使用します。

<UserControl x:Name="ParentView"> 
    <StackPanel>
       <TextBlock>Some Parent View Content here...</TextBlock>
       <!-- Now the child content: -->
       <ContentControl x:Name="UserView" />
    </StackPanel>
</UserControl>

あなたのフレームワークは Robs の元の話に基づいているので、規則に基づいて自動的にプロパティをバインドしていると思いますか? その場合、ここでも同じアプローチが取られます。ContentControlドキュメントに見られるように、の規則は残りの規則とは少し異なります。

ContentControl の規則は少し興味深いものです。バインド先のアイテムが値型でも文字列でもない場合、Content は ViewModel であると想定します。したがって、他の場合のように Content プロパティにバインドする代わりに、CM のカスタム添付プロパティである View.Model を使用してバインドを実際に設定します。このプロパティにより、CM の ViewLocator がビュー モデルの適切なビューを検索し、CM の ViewModelBinder が 2 つをバインドします。それが完了したら、ビューを ContentControl の Content プロパティにポップします。この単一の規則により、フレームワークで強力かつシンプルな ViewModel-First 構成が可能になります。

この規則のコードは次のとおりです。

AddElementConvention<ContentControl>(ContentControl.ContentProperty, "DataContext", "Loaded").GetBindableProperty =
            delegate(DependencyObject foundControl) 
            {
                var element = (ContentControl)foundControl;

                if (element.Content is DependencyObject && !OverwriteContent)
                    return null;
#if SILVERLIGHT
                var useViewModel = element.ContentTemplate == null;
#else
                var useViewModel = element.ContentTemplate == null && element.ContentTemplateSelector == null;
#endif
                if (useViewModel) {
                    Log.Info("ViewModel bound on {0}.", element.Name);
                    return View.ModelProperty;
                }

                Log.Info("Content bound on {0}. Template or content was present.", element.Name);
                return ContentControl.ContentProperty;
            };

ご覧のとおり、Content/ContentTemplateが視覚要素であるかどうかがチェックされ、そうでない場合は VM であると見なされます。バインド可能なプロパティは、VM 自体 (コンテンツ テンプレートが設定されていない場合) またはコンテンツ自体として返されます。

いくつかのアイデアについては、それを読む価値があるかもしれません:

http://caliburnmicro.codeplex.com/wikipage?title=Screens%2c%20Conductors%20and%20Composition&referringTitle=ドキュメント

(準導体セクションまでスクロールします)

アプリ全体でこれを実行してUsersViewModels に置き換えることについては、それを苦労して実行する場合にすぎないと思います

ビュー ファーストのアプローチを使用して、VM を解決するときにファクトリを介してデータ コンテキストを VM に変換することもできますが、面倒なことになります。(絶対に必要でない限り、View-First と ViewModel-First のアプローチを混在させるという考えはあまり好きではありません)

于 2013-05-07T11:16:11.297 に答える