2012-02-15 115 views
15

我剛剛開始了一個新項目,其中表示層將由WPF和由GalaSoft完成MVVM Light如何使用MVVM Light爲WPF導航窗口?

我需要很多意見,我不清楚如何管理通過Windows導航。

首先,在MVVM光所提供的模板來創建一個新的「WPF MVVM查看」創建一個新的Window這是不可能的框架(我的意思是,要使用導航通過把一幀mainView和改變源路徑導航)。

我是否只需將Window更改爲Page就可以使用模板創建的所有視圖?

或者有沒有一種不同的方式來執行MVVM Light工具包中的WPF導航?

回答

12

最後,我這樣做了。

繼o_q的想法之後,我創建了NavigationWindow作爲MainWindow並將所有視圖更改爲頁面。

然後,我創建了一個inteface和使用導航類:

public interface INavigationService 
{ 
    event NavigatingCancelEventHandler Navigating; 
    void NavigateTo(Uri pageUri); 
    void GoBack(); 
} 

public class NavigationService : INavigationService 
{ 
    private NavigationWindow _mainFrame; 

    #region Implementation of INavigationService 

    public event NavigatingCancelEventHandler Navigating; 
    public void NavigateTo(Uri pageUri) 
    { 

     if (EnsureMainFrame()) 
     { 
      _mainFrame.Navigate(pageUri); 
     } 

    } 

    public void GoBack() 
    { 
     if (EnsureMainFrame() 
      && _mainFrame.CanGoBack) 
     { 
      _mainFrame.GoBack(); 
     } 

    } 

    #endregion 

    private bool EnsureMainFrame() 
    { 
     if (_mainFrame != null) 
     { 
      return true; 
     } 

     _mainFrame = System.Windows.Application.Current.MainWindow as NavigationWindow; 

     if (_mainFrame != null) 
     { 
      // Could be null if the app runs inside a design tool 
      _mainFrame.Navigating += (s, e) => 
      { 
       if (Navigating != null) 
       { 
        Navigating(s, e); 
       } 
      }; 

      return true; 
     } 

     return false; 
    } 

} 

然後,在viewModelLocator我創建nedded的路徑存儲到我的視圖的所有常量字符串:

public class ViewModelLocator 
{ 

    #region Views Paths 

    public const string FrontendViewPath = "../Views/FrontendView.xaml"; 
    public const string BackendViewPath = "../Views/BackendView.xaml"; 
    public const string StartUpViewPath = "../Views/StartUpView.xaml"; 
    public const string LoginViewPath = "../Views/LoginView.xaml"; 
    public const string OutOfOrderViewPath = "../Views/OutOfOrderView.xaml"; 
    public const string OperativeViewPath = "../Views/SubViews/OperativeView.xaml"; 
    public const string ConfigurationViewPath = "../Views/SubViews/ConfigurationView.xaml"; 
    #endregion 

在App中。CS,在Application_Startup事件處理程序,有統一的IoC的幫助下,我註冊的NavigationService的單身:現在

public partial class App : System.Windows.Application 
{ 

    private static IUnityContainer _ambientContainer; 
    public static IServiceLocator AmbientLocator { get; private set; } 

    ... 

    private void Application_Startup(object sender, System.Windows.StartupEventArgs e) 
    { 


     _ambientContainer = 
      new UnityContainer(); 

     _ambientContainer.RegisterType<INavigationService, NavigationService>(new ContainerControlledLifetimeManager()); 

     AmbientLocator = new UnityServiceLocator(_ambientContainer); 
     ServiceLocator.SetLocatorProvider(() => AmbientLocator); 

,在我ViewModelLocator,我可以註冊一個「Galasoft」消息捕獲所有的事件並導航到頁面;在構造函數中我有:

public ViewModelLocator() 
    { 
     CreateMain(); 
     CreateFrontend(); 
     CreateBackend(); 
     CreateStartUp(); 
     CreateOperative(); 
     CreateLogin(); 
     CreateConfiguration(); 
     CreateOutOfOrder(); 


     // Set Sturtup Page... 
     ServiceLocator.Current.GetInstance<INavigationService>().NavigateTo(new Uri(StartUpViewPath, UriKind.Relative)); 

     Messenger.Default.Register<MoveToViewMessage>(this, message => 
     { 
      switch (message.StateInfo.StateType) 
      { 
       case StateType.StartUpState: 

        ServiceLocator.Current.GetInstance<INavigationService>().NavigateTo(new Uri(StartUpViewPath,UriKind.Relative)); 
        break; 
       case StateType.LoginState: 
        ServiceLocator.Current.GetInstance<INavigationService>().NavigateTo(new Uri(LoginViewPath, UriKind.Relative)); 
        break; 
       case StateType.OperativeState: 
        ServiceLocator.Current.GetInstance<INavigationService>().NavigateTo(new Uri(OperativeViewPath, UriKind.Relative)); 
        break; 
       case StateType.ConfigurationState: 
        ServiceLocator.Current.GetInstance<INavigationService>().NavigateTo(new Uri(ConfigurationViewPath, UriKind.Relative)); 
        break; 
       case StateType.ClosedState: 
       case StateType.OutOfOrderState: 
        ServiceLocator.Current.GetInstance<INavigationService>().NavigateTo(new Uri(OutOfOrderViewPath, UriKind.Relative)); 
        break; 
       default: 
        ServiceLocator.Current.GetInstance<INavigationService>().NavigateTo(new Uri(StartUpViewPath, UriKind.Relative)); 
        break; 
      } 
     }); 

    } 

這樣,我把所有的的ViewModels「無知」,他們不知道什麼導航,再加上我沒有後面的代碼。

如果我需要通過從視圖按鈕導航,我可以從連接視圖模型解決的NavigationService並導航到該頁面,我需要。

而且,最重要的一點,它的工作原理!

+0

我注意到ViewModelLocator的構造函數在你的例子中不是靜態的,但是它在默認實現中是靜態的... – User1551892 2014-01-29 08:55:45

20

我通常使用ContentControl來顯示動態內容。這是Content屬性通常綁定到CurrentViewModel屬性在父ViewModelDataTemplates用於告訴WPF如何繪製子ViewModels

要更改視圖,只需更改父CurrentViewModel財產ViewModel

你可以找到this article of mine

+0

瑞秋你好,如果你可以張貼的如何實現這個除了你的鏈接一個最小的例子,那簡直太好了。它只是幫助像我這樣的人來到這個答案5年以後的情況下,鏈接不再適用於任何給定的原因 – Ortund 2017-09-12 08:21:35

+0

@Ortund會[本SO答案】(https://stackoverflow.com/a/12216068/302677)幫助?我寫了這個答案已經有一段時間了,但我認爲其他答案的代碼應該是一個合適的例子。 – Rachel 2017-09-12 13:23:48

0

一個例子可導航的應用程序,你會希望你的啓動時視圖是一個NavigationWindow代替

:後面 Window

<NavigationWindow 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 

    x:Class="MainWindow" 
    Title="My Application Title" 
    Height="300" 
    Width="400" /> 

代碼

MVVM Light視圖模板使用Window,但正如您所猜測的那樣,您可以更改它。如果您希望能夠導航到此視圖,請將其設置爲Page。 這是你如何導航:背後

<Page 
    x:Class="Page1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Page1"> 
    <Grid> 
     <!-- this button will navigate to another page --> 
     <Button 
      Content="Go to Page 2" 
      Click="Button_Click" /> 
    </Grid> 
</Page> 

代碼:

using System.Windows; 
using System.Windows.Controls; 

public partial class Page1 : Page 
{ 
    public Page1() 
    { 
     InitializeComponent(); 
    } 

    private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     // the Page class has a property "NavigationService" which allows you to navigate. 
     // you can supply the "Navigate" method with a Uri or an object instance of the page 
     base.NavigationService.Navigate(new Page2()); 
    } 
} 
+0

這可能是一種可能性,即使我不喜歡將代碼放在代碼後面。此外,我忘了告訴你,我的應用程序將是自動售貨機的人機界面,所以我有必要以更簡單的方式瀏覽頁面,例如通過發送來自較低層的事件(用戶不能與表示層交互,因爲沒有鼠標,沒有觸摸屏,沒有鍵盤,ecc ..)。以這種方式瀏覽ViewModel中的頁面是否可能? – zero51 2012-02-16 08:22:25

+0

@ zero51在視圖模型導航的問題,我已經發布了一個解決方案在這裏:?如何瀏覽從一個視圖從Silverlight中的視圖模型另一個視圖(http://stackoverflow.com/a/9304445/1130842) – 2012-02-16 15:30:38

+0

我發現這個職位在galasoft網站[鏈接](http://blog.galasoft.ch/archive/2011/01/06/navigation-in-a-wp7-application-with-mvvm-light.aspx)。它解釋瞭如何在Windows Phone 7中實現導航...我將嘗試使用導航在WPF中實現它。 – zero51 2012-02-17 08:07:18