WPFによってプレゼンテーションレイヤーが実行され、GalaSoftによって MVVM Light が実行される新しいプロジェクトを開始しました。
多くのビューが必要ですが、ウィンドウのナビゲーションを管理する方法がわかりません。
まず、新しい「WPF MVVMビュー」を作成するためにMVVM Lightで提供されるテンプレートは、フレームごとのナビゲーションに使用できない新しいWindow
を作成します(つまり、mainView
と移動するソースパスを変更します)。
テンプレートを使用して作成するすべてのビューのWindow
をPage
に変更する必要があるだけですか?
または、MVVM Lightツールキットを使用してWPFでナビゲーションを実行する別の方法はありますか?
最終的に私はこのようにそれをしました。
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を解決して、必要なページにナビゲートできます。
そして、最も重要なことは、それが機能することです!
通常、ContentControl
を使用して動的コンテンツを表示します。 Content
プロパティは通常、親のCurrentViewModel
プロパティにバインドされていますViewModel
、およびDataTemplates
は、WPFに子の描画方法を指示するために使用されますViewModels
。
ビューを変更するには、親のCurrentViewModel
プロパティを変更するだけですViewModel
この私の記事 で例を見つけることができます
ナビゲート可能なアプリケーションの場合、スタートアップビューを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());
}
}