从Windows Phone 8.1通用应用程序中的视图模型导航到新页面
本文关键字:视图 模型 导航 新页面 应用程序 Phone Windows 1通 | 更新日期: 2023-09-27 18:26:31
我正在开发一款windows phone 8.1通用应用程序,希望找到处理页面导航的最佳方法,而无需在代码后面添加大量逻辑。我希望在我的视图中尽可能保持代码的整洁。可接受的MVVM导航到新页面以响应按钮点击的方式是什么?
我目前必须从ViewModel向视图发送一条RelayComnmand消息,其中包含要导航到的页面的详细信息。这意味着后面的代码必须按如下方式连接:
public MainPage()
{
InitializeComponent();
Messenger.Default.Register<OpenArticleMessage>(this, (article) => ReceiveOpenArticleMessage(article));
...
}
private object ReceiveOpenArticleMessage(OpenArticleMessage article)
{
Frame.Navigate(typeof(ArticleView));
}
这似乎不是最好的方法,尽管它确实有效。如何直接从ViewModel进行页面导航?我在我的项目中使用MVVM Light。
好的,我找到了这个问题的答案。做了一些调查,但我最终找到了首选的MVVM Light方式。无论如何,我不相信这个答案,只是把它发布在这里,以防人们正在寻找这个问题的答案。
创建一个INavigationService接口,如下所示:
public interface INavigationService
{
void Navigate(Type sourcePageType);
void Navigate(Type sourcePageType, object parameter);
void GoBack();
}
按如下方式创建NavigationService类:
public class NavigationService : INavigationService
{
public void Navigate(Type sourcePageType)
{
((Frame)Window.Current.Content).Navigate(sourcePageType);
}
public void Navigate(Type sourcePageType, object parameter)
{
((Frame)Window.Current.Content).Navigate(sourcePageType, parameter);
}
public void GoBack()
{
((Frame)Window.Current.Content).GoBack();
}
}
现在在ViewModelLocator中,设置如下:
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance",
"CA1822:MarkMembersAsStatic",
Justification = "This non-static member is needed for data binding purposes.")]
public MainViewModel Main
{
get
{
return ServiceLocator.Current.GetInstance<MainViewModel>();
}
}
static ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
if (ViewModelBase.IsInDesignModeStatic)
{
SimpleIoc.Default.Register<INavigationService, Design.DesignNavigationService>();
}
else
{
SimpleIoc.Default.Register<INavigationService>(() => new NavigationService());
}
SimpleIoc.Default.Register<MainViewModel>();
}
接下来在设计时设置导航服务如下:
public class DesignNavigationService : INavigationService
{
// This class doesn't perform navigation, in order
// to avoid issues in the designer at design time.
public void Navigate(Type sourcePageType)
{
}
public void Navigate(Type sourcePageType, object parameter)
{
}
public void GoBack()
{
}
}
我的MainViewModel构造函数如下:
public MainViewModel(INavigationService navigationService)
{
_navigationService = navigationService;
...
现在,您可以简单地使用它在视图模型中导航:
_navigationService.Navigate(typeof(WelcomeView));
有关原作者Laurent Bugnion的更多详细信息,请参阅本文和相关代码。http://msdn.microsoft.com/en-us/magazine/jj651572.aspx
这里有一个新的更简单的实现:https://marcominerva.wordpress.com/2014/10/10/navigationservice-in-mvvm-light-v5/
首先,我们创建NavigationService
和DialogService
(用于页面导航参数):
public ViewModelLocator() {
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
var navigationService = this.CreateNavigationService();
SimpleIoc.Default.Register<INavigationService>(() => navigationService);
SimpleIoc.Default.Register<IDialogService, DialogService>();
SimpleIoc.Default.Register<MainViewModel>();
SimpleIoc.Default.Register<DetailsViewModel>();
}
private INavigationService CreateNavigationService() {
var navigationService = new NavigationService();
navigationService.Configure("Details", typeof(DetailsPage));
// navigationService.Configure("key1", typeof(OtherPage1));
// navigationService.Configure("key2", typeof(OtherPage2));
return navigationService;
}
然后,我们在您的ViewModel
中创建一个RelayCommand
和NavigationService
,如下所示:
public class MainViewModel : ViewModelBase {
private INavigationService _navigationService;
public RelayCommand<Tuple<string, string>> DetailsCommand { get; set; }
public MainViewModel(INavigationService navigationService) {
this._navigationService = navigationService;
DetailsCommand = new RelayCommand<Tuple<string, string>>((args) => NavigateTo(args));
}
public void NavigateTo(Tuple<string, string> args) {
this._navigationService.NavigateTo(args.Item1, args.Item1);
}
public void ClickAndNavigate() {
NavigateTo(new Tuple<string, string>("AdminPivotPage", "Test Params"));
}
}
最后,我们可以得到这样的页面导航参数:
public sealed partial class DetailsPage : Page {
// ...
protected override void OnNavigatedTo(NavigationEventArgs e) {
var parameter = e.Parameter as string; // "My data"
base.OnNavigatedTo(e);
}
}
但要阅读MVVM模式中页面导航中传递的参数,您可以在这里查看。
我同意上面的反弹,它更简单,尽管我的直接实现与Blend中的设计数据绑定搞砸了。
我决定创建一个继承自NavigationService 的类
public class NavigationServiceHelper : NavigationService
{
public NavigationServiceHelper()
{
this.Configure("Page1", typeof(View.Page1));
this.Configure("Page2", typeof(View.Page2));
}
}
然后在ViewModelLocator中,我以这种方式注册了
SimpleIoc.Default.Register<INavigationService, NavigationServiceHelper>();
我的设计视图数据绑定再次工作。如果有人能解释为什么设计数据在上面的反弹中不起作用,请解释。谢谢!