Silverlight 4.0 使用MEF重用视图和Viewmodel&;银光

Silverlight 4.0 使用MEF重用视图和Viewmodel&;银光,silverlight-4.0,mef,mvvm-light,Silverlight 4.0,Mef,Mvvm Light,以下是我想做的: 我有一个使用导航框架和MEF的Silverlight应用程序。(像这个:) 此应用程序由一组按钮组成。单击每个按钮可加载视图及其关联的ViewModel 在这些视图中,我有一个包含项目的列表,当我单击每个项目时,它会刷新此视图中的一个子视图 我想创建一个导航系统:例如myapp.aspx#view1/2,其中2实际上是列表中单击的项目。如果我单击其中一个按钮,它将加载一个默认项并刷新所有视图,但当我单击一个项时,我不希望刷新所有视图,而只刷新视图的某些部分(我不希望创建视图和视

以下是我想做的:

我有一个使用导航框架和MEF的Silverlight应用程序。(像这个:) 此应用程序由一组按钮组成。单击每个按钮可加载视图及其关联的ViewModel

在这些视图中,我有一个包含项目的列表,当我单击每个项目时,它会刷新此视图中的一个子视图

我想创建一个导航系统:例如myapp.aspx#view1/2,其中2实际上是列表中单击的项目。如果我单击其中一个按钮,它将加载一个默认项并刷新所有视图,但当我单击一个项时,我不希望刷新所有视图,而只刷新视图的某些部分(我不希望创建视图和视图模型的另一个实例)

我的问题是,当我导航到此已加载的页面(例如从myapp.aspx#view1/2到myapp.aspx#view1/3)时,我希望获得对现有视图或viewmodel的引用的最佳实践(我计划在ContentLoader类的开始加载中这样做) 如果我得到viewmodel,我可以通过更改CurrentItemId属性来实现我想要的功能,该属性可以通过绑定刷新视图


如果您有什么建议,请向davance致谢。

常用的方法是使用某种形式的Messenger来执行此类操作。该项目的点击可能会触发邮件的发送,并附加该项目。所讨论的ViewModel将是订阅者,并编辑其当前设置(即:它的
ItemId
,这将触发绑定刷新)

最常见的实现通常类似于


不过,在这里您可以很容易地进行自定义,特别是因为您已经在使用MEF。只需创建一个服务来处理消息传递,并将其导入两个端点。

常用的方法是使用某种形式的Messenger来执行此类操作。该项目的点击可能会触发邮件的发送,并附加该项目。所讨论的ViewModel将是订阅者,并编辑其当前设置(即:它的
ItemId
,这将触发绑定刷新)

最常见的实现通常类似于


不过,在这里您可以很容易地进行自定义,特别是因为您已经在使用MEF。只需创建一个服务来处理消息传递,并将其导入两个端点。

实际上,当我单击某个项目时,我更愿意使用URI在我的应用程序中导航,但如果我使用URI,则整个视图将重新加载,而不是我想要的特定部分

有了messenger,我想我不能在视图中使用带有url的导航了吧?否则我真的不明白你向我提出了什么建议

我想采用的算法是:

  • 导航(“…asp#MyView1/1”)
    • MyView1是当前视图吗?
      • 是的,然后我想获取当前视图的viewmodel,并将其更改为ItemId属性1
      • 否,则将创建视图
我想在那里实现这个算法:(在我的CompositionNavigationContentLoader类中,每个导航都在这里实例化视图)


谢谢。

事实上,当我点击某个项目时,我更愿意使用URI在我的应用程序中导航,但如果我使用URI,则整个视图将重新加载,而不是我想要的特定部分

有了messenger,我想我不能在视图中使用带有url的导航了吧?否则我真的不明白你向我提出了什么建议

我想采用的算法是:

  • 导航(“…asp#MyView1/1”)
    • MyView1是当前视图吗?
      • 是的,然后我想获取当前视图的viewmodel,并将其更改为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();