2016-05-18 16 views
3

私はWPF MVVMを学習しており、メインウィンドウからボタンをクリックすると新しいウィンドウを開きたいと思っています。ボタンをクリックすると新しいウィンドウが開きます。MVVM

私はそれぞれのViewが同等のViewModelを持っていなければならず、MVVMの基本原則の1つはViewModelがViewについて何も知っていてはいけないということです。

からボタンをクリックして、新しいビューを表示:

だから誰も私に2つのビューと、以下の機能を持つ2つのviewmodelsを作成する方法上の任意のMVVMの原則に違反しない簡単なクリーンな例を提供することができますしてくださいメインビュー。

+0

を無効にしたい場合は、それはMVVMのために、新しいウィンドウを開くことになると、それがトリッキーになります。主な理由の1つは、 'DataTemplate'では' Window'派生クラスを内部で定義することができないということです。ネット上にはさまざまな方法を提供する記事がたくさんあります。私は最初にそれらを読んでみることをお勧めします。それぞれの方法には長所と短所があり、一般的に100%MVVMの原則にも従っていません。 – Jai

答えて

0

使用状況によっては、ビューのコードビハインドからビューを開くときに問題はありません。結局のところビューコードです。あなたはViewModelからウィンドウを開いたりICommandを使用する必要がある場合

MyView view = new MyView(); 
view.Show(); 

そうでない場合、あなたは、私がGitHubに書いたライブラリ「MVVMで開くウィンドウとダイアログ」で見ることができます。これは、MVVMデザインパターンを使用してボタンをクリックしてWindowを開く方法を示します。

+0

私はWPFとMVVMも新しくなっています。しかし、私が理解する限り、これは非常に悪いアプローチです。理由は、ViewModelがこれを行う際にユニットテスト不可能になるためです。 ViewModelフォルダ全体をプルして、Viewが存在しないまま新しいプロジェクトにスローすると、コードはコンパイルされずに実行されます。 – Jai

+0

あなたが私の答えを完全に理解しているかどうかはわかりません。コードビハインドとは、ビューモデルのコードではなく、**ビューの**コードの背後にあることを意味します。 –

+0

申し訳ありませんが、私の悪い、私はコードがViewModelからだと思った。 – Jai

0

私が過去に成功したことは、基本的にView Factoryであるビューを作成し、ビューを作成してビューモデルを割り当てることです。これは、あなたがIoCを使用するのと同じように、ビューのためのスティッキングを行うワンストップショップを私に与えます。

これには利点と不利な点があるかもしれませんので、他にももっと良い方法があるかどうか知りたいのですが、これまでのところ痛みはほとんどありませんでした。 あなたは、このコード(Form1の中にそれを挿入する)を使用することができます:閉じたい場合にも

Form2 frm = new Form2(); 
frm.Show(); 

-2

のは、Form1があなたのメインフォームで、Form2を開きたいものであると言ってみましょうあなたはthis.Close();を使用することができます(現在のフォームを閉じます)。あなただけのForm2を開きたいが、まだForm1が使用できる主な一つであることがあれば はさらに:

Form2 frm = new Form2(); 
frm.Show(); 
this.Focus(); 
+0

これはMVVMではありません。 – user3382285

0

それが一般的な方法で使用することができるようにあなたは、ダイアログとしてビューを起動するための独立したサービスを作成することができますアプリケーション全体でまた、ダイアログを起動したいコンストラクタ経由でこのサービスをViewModelに注入します。

public interface IDialogWindowService<T> 
{ 
    void Show(); 
    void ShowDialog(); 
} 

public class DialogWindowService<T> : IDialogWindowService<T> where T : Window 
{ 
    public void Show() 
    { 
     container.Resolve<T>().Show(); 
    } 

    public void ShowDialog() 
    { 
     container.Resolve<T>().ShowDialog(); 
    } 
} 

それはアプリケーション間で一般的な方法で使用することができるようにあなたは、ダイアログとしてビューを起動するための独立したサービスを作成することができます。また、ダイアログを起動したいコンストラクタ経由でこのサービスをViewModelに注入します。

public interface IDialogWindowService<T> 
{ 
    void Show(); 
    void ShowDialog(); 
} 

public class DialogWindowService<T> : IDialogWindowService<T> where T : Window 
{ 
    public void Show() 
    { 
     container.Resolve<T>().Show(); 
    } 

    public void ShowDialog() 
    { 
     container.Resolve<T>().ShowDialog(); 
    } 
} 

このサービスをそれぞれのビューモデルに挿入するだけです。

public class YourViewModel 
{ 
    //commands 
    public ICommand someCommand { get; set; } 

    private IDialogWindowService<BookingView> _dialogService; 
    public YourViewModel(IDialogWindowService<YourView > dialogService) 
    { 
     _dialogService = dialogService 
     someCommand = new RelayCommand(someCommandDoJob,() => true); 
    } 

    public void someCommandDoJob(object obj) 
    { 
     //Since you want to launch this view as dialog you can set its datacontext in its own constructor.  
     _dialogService.ShowDialog(); 
    } 
} 

OR

あなたはビューを変更するDataTemplatesを使用することができます。これは、動的ViewModelに応じViewsを切り替えることができます:

<Window> 
    <Window.Resources> 
     <DataTemplate DataType="{x:Type ViewModelA}"> 
     <localControls:ViewAUserControl/> 
     </DataTemplate> 
     <DataTemplate DataType="{x:Type ViewModelB}"> 
     <localControls:ViewBUserControl/> 
     </DataTemplate> 
    <Window.Resources> 
    <ContentPresenter Content="{Binding CurrentView}"/> 
</Window> 

Window.DataContextはViewModelAのインスタンスである場合、ViewAが表示され、

Window.DataContextはViewModelBのインスタンスであり、次いでViewBう表示されます。

私が今までに見て読んだ最良の例は、レイチェム・リムによって作られたものです。 See the example.

+0

ViewModelのビューを参照しています:private IDialogWindowService _dialogService;これはMVVMの違反ではありませんか? – whitefang1993

+0

@ whitefang1993 viewModelでビューを参照している場所を表示できますか? – StepUp

+0

YourViewModelクラスでは、 "IDialogWindowService "タイプの参照 "_dialogService"がBookingView型として使用されます。あなたは別のプロジェクトでBookingViewを持っていると言う "IDialogWindowService "の参照を使用するためにそのプロジェクトへの参照を追加する必要はありません?したがって、ViewModels用とView用の2つのプロジェクトがある場合は、ViewViewプロジェクトでViewsプロジェクトを参照して、YourViewModelでBookingViewを使用する必要があります。私が何か誤解した場合は、私を修正してください。私はいくつかのことを明確にしようとしています。 – whitefang1993

0
Window newWindow = new Window(); 
Window.Show(); 

か、前のウィンドウに

Window newWindow = new Window(); 
Window.ShowDialog(); 
関連する問題