2009-09-13 15 views
5

Jak zamknąć widok z ViewModel?Prism2/MVVM Zamknij widok z ViewModel

Mam okno WPF, które zdefiniowało wiele regionów i jest używane jako powłoka do obsługi widoków dla mojej aplikacji. Chciałbym, aby widok mógł usunąć się z regionu lub zamknąć go z kontenera z zakładkami. Jak mogę wykonać to zachowanie z ViewModel.

+0

z cennych uwag od członków i udało się to pomyślnie zakodować. przykładowa klasa implementacji jest publikowana jako odpowiedź na to pytanie. – Raj

Odpowiedz

5

To naprawdę zależy od architektury aplikacji, ale oto jak to zrobić z Prism.

pierwsze chcę powiedzieć, że jest ok mieć swoje odniesienie VM widoku tylko tak długo, jak nie jest to konkretna realizacja View, czyli odniesienia przez interfejs.

Poślubię View i ViewModel za pomocą wtrysku zależności, bardzo podobny do tego, jak to zrobić w StockTraderRI. Mam więc IView i IViewModel. IViewModel ma proprium o nazwie "Widok" typu IView.

Z warstwy kodu (dla mnie, zwykle kontroler ... patrz StockTraderRI), która współpracuje z twoimi regionami, dodaj mechanizm, aby usunąć swój widok z regionu.

Na przykład:

myRegion.Remove(myIViewModel.View); 

Jeśli regiony są obsługiwane przez sterownik, może chcesz umieścić proste zdarzenie na VM powiadomić, gdy VM chce być „zamknięty”. Możesz także eksperymentować z IEventAggregatorem, jeśli chcesz użyć słabego modelu zdarzeń. Jeśli region jest obsługiwany w VM, po prostu dodaj tam ten kod.

+0

Dzięki. Myślę, że mam logikę. Ale utknąłem w miejscu, w którym rozwiązuję interfejs kontrolera z modułu. Otrzymuję wyjątek przepełnienia stosu. LoginController controller = this.container.Resolve (); zgłasza błąd. Jakieś sugestie? – Raj

+0

Wygląda na to, że twój kontener jedności ma włączone niektóre okrężne zależności i/lub jest niepoprawnie skonfigurowany. Chciałbym śledzić wszystkie konstruktory i upewnić się, że każdy wprowadzony parametr wygląda poprawnie. Jeśli możesz spróbować wkleić kod instalacji kontenera i może kilka klas konstruktorów. –

+0

Witaj, pls sprawdź kod, który wkleiłem jako odpowiedź na to pytanie. Dzięki jeszcze raz. – Raj

7

Ponieważ numer ViewModel nie ma (i nie powinien) mieć odniesienia do View, nie można go zamknąć bezpośrednio. Możesz jednak dodać do swojego urządzenia Event w swoim telefonie, aby wskazać, że chce się zamknąć.

Josh Smith napisał: an article pokazujący, jak to zrobić (około połowy artykułu).

+1

Cześć dzięki, już to przeżyłem. Ale artykuł Josh nie używa CompositeWPF, więc zastanawiam się, w jaki sposób mógłbym wdrożyć taką obsługę zdarzeń w połączeniu z Regions i Bootstrapper Composite WPF. – Raj

+1

Zrobiłbyś ten kod i zamiast window.Close() jako obsługi, użyłbyś regionMananger.Regions ["MyRegion"]. Usuń (okno) –

+0

Dobry artykuł, przy okazji. –

3

To jak mój moduł logowania wygląda następująco:

public class LoginModule : IModule 
{ 
    private readonly IUnityContainer container; 

    public LoginModule(IUnityContainer container) 
    { 
     this.container = container; 
    } 

    #region IModule Members 

    public void Initialize() 
    { 
     this.container.RegisterType<ILoginController, LoginController>(new ContainerControlledLifetimeManager()); 
     this.container.RegisterType<ILoginView, LoginView>(); 
     this.container.RegisterType<ILoginViewModel, LoginViewModel>(); 

     ILoginController controller = this.container.Resolve<ILoginController>(); 
     controller.Run(); 
    } 

    #endregion 
} 

Jest to kontroler:

public class LoginController : ILoginController 
{ 
    private readonly IRegionManager regionManager; 
    private readonly ILoginViewModel model; 

    public LoginController(IRegionManager regionManager, ILoginViewModel model) 
    { 
     this.regionManager = regionManager; 
     this.model = model; 
     model.RequestClose += new EventHandler(model_RequestClose); 
    } 

    void model_RequestClose(object sender, EventArgs e) 
    { 
     regionManager.Regions["LoginRegion"].Remove(model.View); 
    } 

    #region ILoginController Members 

    public void Run() 
    { 
     // Register views here 
     regionManager.Regions["LoginRegion"].Add(model.view); 
    } 

    #endregion 
} 

A to mój ViewModel:

public class LoginViewModel : ViewModelBase, ILoginViewModel 
{ 
    IEventAggregator _eventAggregator; 
    RelayCommand _loginCommand; 
    private readonly UserProfileRepository _userProfileRepository; 
    public event EventHandler RequestClose; 

    public ICommand LoginCommand 
    { 
     get 
     { 
      if (_loginCommand == null) 
      { 
       _loginCommand = new RelayCommand(
        param => this.Login(), 
        param => this.IsValid()); 
      } 
      return _loginCommand; 
     } 
    } 

    public LoginViewModel(IEventAggregator eventAggregator, UserProfileRepository userProfileRepository, ILoginView view) 
    { 
     this._eventAggregator = eventAggregator; 
     this._userProfileRepository = userProfileRepository; 
     this.View = view; 
    } 

    #region ILoginViewModel Members 

    public ILoginView View { get; private set; } 

    #endregion 
}