【问题标题】:Reusing Views and Viewmodel with MEF & Silverlight使用 MEF 和 Silverlight 重用视图和视图模型
【发布时间】:2011-02-21 17:04:13
【问题描述】:
这是我想做的:
我有一个使用导航框架和 MEF 的 Silverlight 应用程序。 (喜欢这个:http://msdn.microsoft.com/en-us/magazine/gg535672.aspx)
此应用程序由一组按钮组成。每次单击按钮都会加载一个视图及其关联的 ViewModel。
在这些视图中,我有一个包含项目的列表,当我单击每个项目时,它会刷新此视图中的一种子视图。
我想创建一个导航系统:例如 myapp.aspx#view1/2,其中 2 实际上是在列表中单击的项目。如果我单击其中一个按钮,它将加载一个默认项目并刷新所有视图,但是当我单击一个项目时,我不想刷新所有视图,而只刷新视图的某些部分(我不想要创建视图和视图模型的另一个实例)。
我的问题实际上是当我导航到已经加载的这个页面时(例如从 myapp.aspx#view1/ 2到myapp.aspx#view1/3)(我打算在ContentLoader类的BeginLoad中做这个)
如果我获得了视图模型,我可以通过更改当前 itemId 属性来完成我想要的操作,该属性可以通过绑定刷新视图。
如果您有什么要提议的,非常感谢。
【问题讨论】:
标签:
silverlight-4.0
mef
mvvm-light
【解决方案1】:
一种常见的方法是使用某种形式的 Messenger 来执行此类操作。该项目的点击可以触发消息的发送,并附加该项目。有问题的 ViewModel 将是订阅者,并编辑其当前设置(即:它是 ItemId,这将触发绑定刷新)。
最常见的实现通常类似于Messenger service in MVVM Light。
不过,在这里推出您自己的产品相当容易,尤其是因为您已经在使用 MEF。只需创建一个服务来处理消息传递,并将其导入两个端点。
【解决方案2】:
实际上,当我单击一个项目时,我更愿意使用 URI 在我的应用程序中导航,但如果我使用 URI,则整个视图会重新加载,而不是我想要的特定部分。
我认为,有了信使,我将无法在视图中使用带有 url 的导航?否则我并没有真正弄清楚你向我提出了什么建议。
我想采用的算法是:
- 导航("...asp#MyView1/1")
- MyView1 是当前视图?
- 是的,那么我想获取当前视图的视图模型并将其 ItemId 属性更改为 1
- 不,那么将创建视图
我想在那里实现这个算法:(这是在我的 CompositionNavigationContentLoader 类中为每个导航实例化视图的地方)
public IAsyncResult BeginLoad(Uri targetUri, Uri currentUri, AsyncCallback userCallback, object asyncState)
{
// Convert to a dummy relative Uri so we can access the host.
var relativeUri = new Uri("http://" + targetUri.OriginalString, UriKind.Absolute);
// Get the factory for the ViewModel.
var viewModelMapping = ViewModelExports.FirstOrDefault(o => o.Metadata.Key.Equals(relativeUri.Host, StringComparison.OrdinalIgnoreCase));
if (viewModelMapping == null)
throw new InvalidOperationException(
String.Format("Unable to navigate to: {0}. Could not locate the ViewModel.", targetUri.OriginalString));
// Get the factory for the View.
var viewMapping = ViewExports.FirstOrDefault(o => o.Metadata.ViewModelContract == viewModelMapping.Metadata.ViewModelContract);
if (viewMapping == null)
throw new InvalidOperationException(
String.Format("Unable to navigate to: {0}. Could not locate the View.", targetUri.OriginalString));
// Resolve both the View and the ViewModel.
var viewFactory = viewMapping.CreateExport();
var view = viewFactory.Value as Control;
var viewModelFactory = viewModelMapping.CreateExport();
var viewModel = viewModelFactory.Value as IViewModel;
// Attach ViewModel to View.
view.DataContext = viewModel;
viewModel.OnLoaded();
谢谢。