2013-05-20 17 views
9

Powiedzmy mam MainWindow i MainViewModel, nie używam MVVM światła lub Prism w tym przykładzie.
W tym MainWindow chcę kliknąć MenuItem lub Button, aby otworzyć NewWindow.xaml, a nie UserControl.
Wiem, jak to zrobić z UserControl, aby otworzyć nowe UserControl w moim istniejącym oknie w ContrntControl lub Frame.otworzyć nowe okno w MVVM

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

Kod

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

W ResourceDitionary dla MainWindow mam:

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

Chodzi o to, że chcę otworzyć nowy Window, a nie UserControl. Więc korzystać z niektórych kodu:

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(); 
} 

a potem wiążą OpenNewWindow do MenuItem lub Button.
Wiem, że to nie jest właściwa droga, ale jaki jest właściwy sposób, aby to zrobić?

Dzięki!

+0

Dlaczego uważasz, że nie jest to właściwy sposób. Masz powiązanie ICommand, które wykonuje działanie. (To wydaje się poprawne?) – sircodesalot

+1

byłoby problem z testowaniem tego ViewModelu, ponieważ byłby on zależny od klasy NewWindowViewModel, gdybym cretował instanece w metodzie DoOpeNewWindow(), która jest w MainViewMOdel –

Odpowiedz

21

Są dwa problemy, które należy rozwiązać za pomocą tego typu aplikacji.

Po pierwsze, nie chcesz, aby Model Widok tworzył i wyświetlał komponenty interfejsu użytkownika bezpośrednio. Jedną z motywacji do korzystania z MVVM jest wprowadzenie zdolności testowej do modelu widoku, a pojawienie się tej klasy w nowych oknach sprawia, że ​​ta klasa jest trudniejsza do przetestowania.

Drugi problem, który należy rozwiązać, to jak rozwiązać zależności w aplikacji lub w tym przypadku - jak "podłączyć" model widoku do odpowiedniego widoku? Możliwe do utrzymania rozwiązanie tego ostatniego problemu wynika z zastosowania pojemnika DI. Bardzo dobre odniesienie do tego tematu podaje Mark Seemann's Dependency Injection in .NET. W rzeczywistości omawia także, jak rozwiązać pierwszy problem!

Aby rozwiązać poprzedni problem, należy wprowadzić warstwę kodu pośredniczącego do kodu, aby model widoku nie był zależny od konkretnej implementacji tworzenia nowego okna. Bardzo prosty przykład podano w poniższym kodzie:

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 
} 

pamiętać, że podjęcie realizacji IWindowFactory w konstruktorze swojej View-model i to do tego obiektu, że stworzenie nowego okna jest delegowanego do. Pozwala to zastąpić implementację produkcyjną inną podczas testowania.

+0

bardzo dobrym rozwiązaniem, wiem, że Mam do czynienia z DI. Chciałem Cię zapytać, czy jest to podejście typu IWindowFactory a Factory Pattern. Więc to jest w zasadzie delegowane do Factory, aby utworzyć ten ViewModel? –

+0

Zadaniem IWindowFactory jest po prostu przekazanie faktycznego utworzenia okna do abstrakcji (która może być później zastąpiona podczas testowania). W tym sensie, że ukrywa implementację dla rzeczywistego tworzenia - tak, jest to podejście Factory Pattern. – Lawrence

+0

oke działało na mój przykład dzięki :) –

Powiązane problemy