我刚刚开始了一个新项目,其中表示层将由WPF完成,MVVM Light由GalaSoft完成。
我需要很多观点,而且我不清楚如何通过窗口管理导航。
首先,MVVM Light中提供的用于创建新“WPF MVVM视图”的模板创建了一个新的Window
,它不能用于逐帧导航(我的意思是,在{ {1}}并更改源路径以进行导航。
对于我使用模板创建的所有观看次数,我是否只需将mainView
更改为Window
?
或者是否有不同的方法在WPF中使用MVVM Light工具包执行导航?
答案 0 :(得分:20)
我通常使用ContentControl
来显示动态内容。它的Content
属性通常绑定到父CurrentViewModel
中的ViewModel
属性,而DataTemplates
用于告诉WPF如何绘制子ViewModels
。
要更改视图,只需更改父CurrentViewModel
ViewModel
属性即可
找到示例
答案 1 :(得分:14)
最终我这样做了。
遵循o_q的想法,我将NavigationWindow创建为MainWindow,并将所有视图更改为page。
然后,我使用Navigation创建了一个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中,我创建了所有const字符串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事件处理程序中,在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;
}
});
}
通过这种方式,我保持所有viewModel“无知”......他们对导航一无所知,而且我没有代码。
如果我需要使用视图中的按钮进行导航,我可以从连接的viewModel解析NavigationService并导航到我需要的页面。
最重要的是,它有效!
答案 2 :(得分: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" />
代码背后:
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());
}
}