Mvvm 初始化视图模型
MVVM一直让我感到困惑——如果我使用视图优先的方法来构建我的对象(这似乎是最常见的方法,至少在经过大量阅读和搜索之后),我如何将上下文信息获取到viewmodel中 我看到许多类似问题的答案都是“使用DI容器注入模型”,但这对我没有帮助,所以我将提供一个小示例 假设我的应用程序是PeopleEditor。它用于加载和编辑复杂的人物对象。当你加载应用程序时,你会看到一个主屏幕,它将一群人加载到内存中——比如说,这些人都可以通过我可以从我的容器中访问的集合来访问。通过单击一个人,您将进入编辑器屏幕。编辑器很复杂,因此这不是一个在一个屏幕中实现的简单的主细节视图 因此,在主屏幕上,当我单击一个人时,应用程序需要创建一个新的视图和viewmodel并显示视图。如果我首先通过容器或不通过容器创建viewmodel,我可以使用适当的person对象初始化它这对我来说很自然,所以我很难弄清楚为什么“视图优先”似乎是主要的模式。如何使用“视图优先”方法?视图将创建viewmodel,它可以访问人员集合,但不知道编辑的是谁。为清晰起见进行编辑:一次可以存在多个人员编辑器,每个编辑器编辑不同的人员 Prism 4.0 alpha的MVVM参考实现使用“状态处理程序”,这基本上是应用程序用于在容器中存储构造函数参数的服务。它保存状态并调用ShowView,最终创建的viewmodel导入状态对象。这对我来说似乎很笨拙——就像它试图假装它是松散耦合的,而实际上它不是。还有其他人有其他指导吗?nlawalker 我不是专家,但我对“视图优先”和“模型优先”的了解是:Mvvm 初始化视图模型,mvvm,silverlight-4.0,Mvvm,Silverlight 4.0,MVVM一直让我感到困惑——如果我使用视图优先的方法来构建我的对象(这似乎是最常见的方法,至少在经过大量阅读和搜索之后),我如何将上下文信息获取到viewmodel中 我看到许多类似问题的答案都是“使用DI容器注入模型”,但这对我没有帮助,所以我将提供一个小示例 假设我的应用程序是PeopleEditor。它用于加载和编辑复杂的人物对象。当你加载应用程序时,你会看到一个主屏幕,它将一群人加载到内存中——比如说,这些人都可以通过我可以从我的容器中访问的集合来访问。通过单击一个人,您将进入编辑器屏幕
//selectedPeople is contextual object
myPeopleDetailVM.LoadData(selectedPeople)
将selectedPeople
传递给事件总线的参数时,情况基本相同
若您考虑性能,那个么您可以将其和在这种情况下的路由策略进行比较。路由策略比事件总线更复杂。我认为,若您对使用WPF路由事件有足够的信心,那个么使用事件聚合器应该比使用事件聚合器更有信心
我看到的唯一问题是,如果您使用内置框架事件聚合器(prism、mvvmlight),您的viewmodel会被事件总线污染,如果您对此抱怨,那么我同意您的看法
希望有帮助。如果您使用的是Prism,您可以通过使用其导航功能轻松、灵活地解决此问题。使用IRegionManager.RequestNavigate,通过构造目标视图的Uri以包含用于相应人员标识的查询字符串参数,从主视图导航到编辑视图。您可以在目标视图模型的OnNavigatedTo()方法实现中提取该id(INavigationAware成员。视图模型应实现此接口) 您可以在Prism下载附带的“查看切换导航”示例应用程序中看到这一点。它位于Quickstarts文件夹下 从同一示例应用程序(模仿Outlook)中,以下代码用于从InboxView导航到EmailView,以便从收件箱打开特定的电子邮件:
var builder = new StringBuilder();
builder.Append(EmailViewKey);
var query = new UriQuery();
query.Add(EmailIdKey, document.Id.ToString("N"));
builder.Append(query);
this.regionManager.RequestNavigate(RegionNames.MainContentRegion, new Uri(builder.ToString(), UriKind.Relative));
在EmailView的视图模型EmailViewModel中,要打开的电子邮件是从导航上下文中提取的,如下所示:
void INavigationAware.OnNavigatedTo(NavigationContext navigationContext)
{
// todo: 15 - Orient to the right context
//
// When this view model is navigated to, it gathers the
// requested EmailId from the navigation context's parameters.
//
// It also captures the navigation Journal so it
// can offer a 'go back' command.
var emailId = GetRequestedEmailId(navigationContext);
if (emailId.HasValue)
{
this.Email = this.emailService.GetEmailDocument(emailId.Value);
}
this.navigationJournal = navigationContext.NavigationService.Journal;
}
private Guid? GetRequestedEmailId(NavigationContext navigationContext)
{
var email = navigationContext.Parameters[EmailIdKey];
Guid emailId;
if (email != null && Guid.TryParse(email, out emailId))
{
return emailId;
}
return null;
}
当你说viewmodel对你来说更自然时,为什么不想使用viewmodel优先的方法呢?marlon grech说view或viewmodel first是个人偏好的选择(viewfirst更容易与之混合使用)。我也这么认为,我使用的方法最适合我的场景。所以我在我的应用程序中混合了这两种,这取决于我想做什么。有趣的问题。我总是问自己关于“视图优先”方法的同样问题。。。viewmodel首先看起来更自然,所以我总是这样use@blindmeis:谢谢你的回复。这并不是说我不想先使用viewmodel——事实上,这就是我现在构建应用程序的方式——只是我很好奇如何以视图优先的方式实现它。我试图在我的应用程序中实现的目标对我来说似乎相当普遍,而viewmodel首先似乎非常简单