2012-02-15 22 views
15

私は、プレゼンテーションレイヤーをWPFで、MVVM LightでGalaSoftが行う新しいプロジェクトを開始しました。MVVM Light for WPFでウィンドウをナビゲートするにはどうすればいいですか?

私はたくさんの意見が必要ですが、ウィンドウを通したナビゲーションの管理方法はわかりません。

まず、新しいWPF MVVMビューを作成するためにMVVM Lightで提供されているテンプレートでは、フレーム単位でのナビゲーションには使用できない新しいWindowが作成されます(つまり、mainViewにフレームを置き、ナビゲートするソースパス)。

テンプレートを使用して作成したすべてのビューについて、WindowからPageに変更するだけですか?

または、MVVM Lightツールキットを使用してWPFでナビゲーションを実行する別の方法はありますか?

答えて

12

結局、私はそれをこのようにしました。

o_qのアイデアに従って、NavigationWindowをMainWindowとして作成し、すべてのビューをページに変更しました。

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 

:私は私の意見へのパスを格納するneddedすべてのconst文字列を作成しviewModelLocatorで、

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

} 

その後:

その後、私はintefaceをとナビゲーションを使用してクラスを作成しましたアプリ内で

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」のメッセージを登録することができますし、に移動:CS、Application_Startupイベントハンドラでは、ユニティのIoCの助けを借りて、私はのNavigationServiceのシングルトンを登録しましたページ;私が持っているコンストラクタで:

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を保つ...彼らは、ナビゲーションについて何も知らない、プラス私は背後にあるコードを持っていません。

ビューからボタンを使用してナビゲートする必要がある場合は、接続されているviewModelからNavigationServiceを解決し、必要なページに移動できます。

そして、最も重要なこと、それは動作します!

+0

私はViewModelLocatorコンストラクタがあなたの例では静的ではないことに気付きましたが、デフォルト実装では静的です... – User1551892

20

通常、動的コンテンツを表示するにはContentControlを使用します。 Contentのプロパティは、通常、親ののプロパティにバインドされています。ViewModelDataTemplatesは、子を描画する方法をWPFに指示するために使用されます。ViewModels

単にあなたが航行アプリケーションについてthis article of mine

+0

こんにちはRachelさん、あなたのリンクに加えてこれを実装する方法の最小限の例を投稿できるなら、それはすばらしいことでしょう。それはちょうど私のような人々がこの答えに来るのを助ける5年後何らかの与えられた理由のためにリンクがもはや働いている場合のために – Ortund

+0

@Ortundさん[ヘルプ](https://stackoverflow.com/a/12216068/302677)助け?私はこの答えを書いてからしばらくしていますが、私はその他の答えのコードが適切な例であるべきだと思います。 – Rachel

0

で例を見つけることができ、親ViewModel

CurrentViewModelプロパティを変更し、ビューを変更するには、あなたはあなたのスタートアップビューではなく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ライトビューテンプレートは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

+0

@ zero51 viewmodelでのナビゲーションの問題について、私はここに解決策を掲載しました:[Silverlightでviewmodelから別のビューにナビゲートする方法](http://stackoverflow.com/a/9304445/1130842) –

+0

この記事はgalasoftのサイト[link](http://blog.galasoft.ch/archive/2011/01/06/navigation-in-a-wp7-application-with-mvvm-light.aspx)で見つかりました。 Windows phone 7でナビゲーションを実装する方法を説明します...ナビゲーションを使用してWPFで実装しようとします。 – zero51

関連する問題