web-dev-qa-db-ja.com

WPF MVVMまっすぐなXAMLウィンドウビューではなく、ContentControl + DataTemplateビューを使用する理由

WPFのMVVMについて質問があり、私を苦しめています。

なぜこのようなことをしますか?

MainWindow.xaml:

<Window x:Class="MVVMProject.MainWindow"
    xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml">
    <Grid>
        <ContentControl Content="{Binding}"/>
    </Grid>
</Window>

ExampleView.xamlを次のようにセットアップします。

<ResourceDictionary xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
    xmlns:vms="clr-namespace:MVVMProject.ViewModels">
    <DataTemplate DataType="{x:Type vms:ExampleVM}" >
        <Grid>
            <ActualContent/>
        </Grid>
    </DataTemplate>
</ResourceDictionary>

そして、次のようなウィンドウを作成します。

public partial class App : Application {

    protected override void OnStartup(StartupEventArgs e) {

        base.OnStartup(e);

        MainWindow app = new MainWindow();
        ExampleVM context = new ExampleVM();
        app.DataContext = context;
        app.Show();
    }
}

このようにできるとき:?

App.xaml:(スタートアップウィンドウ/ビューの設定)

<Application x:Class="MVVMProject.App"
    xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
    StartupUri="ExampleView.xaml">
</Application>

ExampleView.xaml:(ResourceDictionaryではないウィンドウ)

<Window x:Class="MVVMProject.ExampleView"
    xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
    xmlns:vms="clr-namespace:MVVMProject.ViewModels">
    >
    <Window.DataContext>
        <vms:ExampleVM />
    </Window.DataContext>

    <Grid>
        <ActualContent/>
    </Grid>
</Window>

基本的には「DataTemplateとして表示」(VaD)vs.「Windowとして表示」(VaW)

比較についての私の理解は次のとおりです(VS 2008を使用しているため、Blendabilityやその他のものが不足していることに注意してください)。

  • VaD:ウィンドウを閉じずにビューを切り替えることができます。 (これは私のプロジェクトには望ましくありません)
  • VaD:VMはビューについてまったく何も知りませんが、VaWでは(のみ)別のウィンドウを開くときにインスタンス化できる必要があります
  • VaW:デザイナでレンダリングされたxamlを実際に見ることができます(少なくとも現在の設定ではVaDではできません)
  • VaW:ウィンドウの開閉で直感的に動作します。各ウィンドウには、対応するビュー(およびViewModel)があります(is)
  • VaD:ViewModelは、プロパティを介して初期ウィンドウ幅、高さ、サイズ変更可能性などを渡すことができます(VaWではウィンドウに直接設定されます)
  • VaW:FocusManager.FocusedElementを設定できます(VaDの方法がわからない)
  • VaW:私のウィンドウタイプ(リボン、ダイアログなど)がビューに組み込まれているため、ファイルが少ない

ここで何が起こっているのでしょうか? XAMLでウィンドウを構築し、VMのプロパティを介してデータにクリーンにアクセスし、それで完了することはできませんか?コードビハインドは同じです(実質的にnil)。 Viewのすべての項目をResourceDictionaryにシャッフルする必要がある理由を理解するのに苦労しています。 (しかし、私はやりたくないwrong;-))


それも重要ですか?見逃したことはありますか?読んでくれてありがとう。 :O


MVVMの理解を深めてくれたRachel LimとNick Polyakに感謝します

編集:マイナーフローの変更

74
Simon F

ViewModelに応じて動的にビューを切り替える場合、人々はDataTemplatesをそのように使用します。

<Window>
    <Window.Resources>
       <DataTemplate DataType="{x:Type local:VM1}">
          <!-- View 1 Here -->
       </DataTemplate>

       <DataTemplate DataType="{x:Type local:VM2}">
          <!-- View 2 here -->
       </DataTemplate>
    </Window.Resources>

    <ContentPresenter Content="{Binding}"/>

</Window>

そう、

Window.DataContextVM1のインスタンスである場合、View1が表示されます。

で、もし

Window.DataContextVM2のインスタンスであり、View2が表示されます。

確かに、1つのビューのみが予想され、変更されない場合はまったく意味がありません。

私はこれが十分に明確であることを願っています:P

121

VaDでは、ビューモデルはビューについて何も知らないため、ビューモデルのみでビューなしで完全に機能する完全に機能するアプリケーションを構築できます。これにより、完全にコードで駆動できるアプリケーションを作成できるようになります。これにより、GUIなしで統合テストを実行できるようになります。 GUIを介した統合テストは脆弱であることが悪名高い-ビューモデルを介したテストはより堅牢である必要があります。

8
Phillip Ngan

私の個人的な経験から:両方の作業モデルは、あなたが望むものに依存し、アプリケーションの要件に依存します。 VaDの背後にある考え方は、コンテンツとコンテナーを切り離すことです。 VaDを実装すると、このタイプのアイテムを表示するたびに(デフォルトで)このテンプレートを使用できます。 ItemsControls(リスト、リストビュー、グリッドなど)およびContentControlsでのみバインディングを使用できます。あなたが言ったように、VaDは、新しいウィンドウを閉じたり開いたりすることなく、ウィンドウのコンテンツを切り替えるために機能します。また、UserControlsを使用してビューを定義し、フォーカスされた要素があれば制御し、コードビハインドを管理することもできます。したがって、データテンプレートは次のようになります。

<ResourceDictionary xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
xmlns:vms="clr-namespace:MVVMProject.ViewModels">
<DataTemplate DataType="{x:Type vms:ExampleVM}" >
    <CustomUserControl A="{Binding A}" B="{Binding B}" DataContext="{Binding}" .../>
</DataTemplate>

UserControlで依存関係プロパティを設定することもできます。これにより、アプリのバインドと分離が許可されるため、作業が簡単になります。

しかし、もちろん、アプリが動的にコンテンツの切り替えを必要としない場合、メインウィンドウまたはその他のウィンドウにVaWを使用することは問題ありません。実際、VaWVaDの両方を使用できます。この最後のものは、ウィンドウを必要としないアプリの内部アイテムに使用できます。アプリケーションの要件と、アプリの開発にかかる時間に応じて、何が良いかを選択します。この個人的な経験が役立つことを願っています...

5
Raúl Otaño