2013-05-20 12 views
9
で新しいウィンドウ

は、私がMainWindowMainViewModelを持っていると言うことができます、私は、この例ではMVVMライトまたはプリズムを使用していませんよ。
このMainWindow またはButtonをクリックして、NewWindow.xamlではなくUserControlを開きます。
UserControlでこれを使用して、ContrntControlまたはFrameの既存のウィンドウに新しいUserControlを開く方法を知っています。オープンMVVM

<ContentControl Content="{Binding Path=DisplayUserControl,UpdateSourceTrigger=PropertyChanged}" /> 

MainWindowためResourceDitionary

public ViewModelBase DisplayUserControl 
{ 
    get 
    { 
     if (displayUserControl == null) 
     { 
      displayUserControl = new ViewModels.UC1iewModel(); 
     } 
     return displayUserControl; 
    } 
    set 
    { 
     if (displayUserControl == value) 
     { 
      return; 
     } 
     else 
     { 
      displayUserControl = value; 
      OnPropertyChanged("DisplayUserControl"); 
     } 
    } 
} 

コード私が持っている:

<DataTemplate DataType="{x:Type localViewModels:UC1ViewModel}"> 
    <localViews:UC1 /> 
</DataTemplate> 
<DataTemplate DataType="{x:Type localViewModels:UC2ViewModel}"> 
    <localViews:UC2 /> 
</DataTemplate> 

事は、私は新しいWindow、ないUserControl開きたいということです。

private ICommand openNewWindow; 

public ICommand OpenNewWindow 
{ 
    get { return openNewWindow; } 
} 

public void DoOpenNewWindow() 
{ 
    View.NewWindowWindow validationWindow = new View.NewWindow(); 
    NewWindowViewModel newWindowViewModel = new NewWindowViewModel(); 
    newWindow.DataContext = ewWindowViewModel; 
    newWindow.Show(); 
} 

、その後MenuItemまたはButtonにバインドOpenNewWindow:だから私はこのようないくつかのコードを使用します。
これは正しい方法ではありませんが、これを行う正しい方法は何ですか?

ありがとうございます!

+0

なぜそれが正しい方法ではないと思いますか?アクションを実行しているICommandバインディングがあります。 (正確そうですか?) – sircodesalot

+1

MainViewMOdelのDoOpeNewWindow()メソッドのインスタンスを作成したので、NewWindowViewModelクラスに依存するため、ViewModelをテストするのが問題になります。 –

答えて

21

このタイプのアプリケーションで解決する必要がある2つの問題があります。

最初に、View-Modelを作成してUIコンポーネントを直接表示したくないとします。 MVVMを使用する動機の1つは、View-Modelにテスト能力を導入することです。このクラスを新しいウィンドウにポップアップさせると、このクラスをテストするのが難しくなります。

解決する必要があるもう1つの問題は、アプリケーションの依存関係を解決する方法です。このインスタンスでは、ビューモデルを対応するビューにどのようにフックアップするのですか?この後者の問題に対する維持可能な解決法は、DIコンテナの使用によって与えられる。この主題に対する非常に良い言及は、Mark SeemannのDependency Injection in .NETによって与えられる。彼は実際にも最初の問題を解決する方法についても議論しています!

前の問題を解決するには、新しいウィンドウを作成する具体的な実装にView-Modelを依存させないように、コードに間接レイヤーを導入する必要があります。あなたはあなたのビューモデルのコンストラクタでIWindowFactoryの実装を取り、そしてそれは、新しいウィンドウの作成が委任されていることをこのオブジェクトにあることを

public class ViewModel 
{ 
    private readonly IWindowFactory m_windowFactory; 
    private ICommand m_openNewWindow; 

    public ViewModel(IWindowFactory windowFactory) 
    { 
     m_windowFactory = windowFactory; 

     /** 
     * Would need to assign value to m_openNewWindow here, and associate the DoOpenWindow method 
     * to the execution of the command. 
     * */ 
     m_openNewWindow = null; 
    } 

    public void DoOpenNewWindow() 
    { 
     m_windowFactory.CreateNewWindow(); 
    } 

    public ICommand OpenNewWindow { get { return m_openNewWindow; } } 
} 

public interface IWindowFactory 
{ 
    void CreateNewWindow(); 
} 

public class ProductionWindowFactory: IWindowFactory 
{ 

    #region Implementation of INewWindowFactory 

    public void CreateNewWindow() 
    { 
     NewWindow window = new NewWindow 
      { 
       DataContext = new NewWindowViewModel() 
      }; 
     window.Show(); 
    } 

    #endregion 
} 

注:非常に簡単な例を以下のコードに示されていますに。これにより、テスト中に本番実装を別のものに置き換えることができます。

+0

非常に良い解決策です私はここでDIを扱わなければならない。私はあなたにIWindowFactoryファクトリパターンアプローチであることを尋ねたがっています。これは基本的に、ViewModelを作成するためにFactoryに委譲されていますか? –

+0

IWindowFactoryの目的は、ウィンドウの実際の作成を抽象化(後でテスト中に置き換えることができる)に単純に委譲することです。実際の作成のための実装が隠れているという意味では、そうです。それはファクトリパターンのアプローチです。 – Lawrence

+0

それは私の例のために働いてくれました:) –