web-dev-qa-db-ja.com

MVVM Light for WPFでウィンドウをナビゲートする方法は?

WPFによってプレゼンテーションレイヤーが実行され、GalaSoftによって MVVM Light が実行される新しいプロジェクトを開始しました。

多くのビューが必要ですが、ウィンドウのナビゲーションを管理する方法がわかりません。

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

テンプレートを使用して作成するすべてのビューのWindowPageに変更する必要があるだけですか?

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

18
zero51

最終的に私はこのようにそれをしました。

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

次に、ナビゲーションを使用するインターフェースとクラスを作成しました。

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で、ビューへのパスを格納するためにnedされたすべてのconst文字列を作成しました。

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イベントハンドラーで、Unity 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を「無知」に保ちます...彼らはナビゲーションについて何も知りません。さらに、背後にコードはありません。

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

そして、最も重要なことは、それが機能することです!

14
zero51

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

ビューを変更するには、親のCurrentViewModelプロパティを変更するだけですViewModel

この私の記事 で例を見つけることができます

21
Rachel

ナビゲート可能なアプリケーションの場合、スタートアップビューを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" />

コードビハインド:

using System.Windows.Navigation;

public partial class MainWindow : NavigationWindow
{
    public MainWindow()
    {
        InitializeComponent();
    }
}

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
o_q