根据导航区域将参数传递给ViewModel构造函数?

时间:2016-01-07 15:00:37

标签: c# wpf mvvm prism

我有一个WPF应用程序,我尝试逐步转移到Prism。当前步骤是RegionManager和NavigationService / Composite UI。

我确实实现了一个自己的RegionManager和NavigationService来处理细节,现在我尝试用Prism RegionManager替换自己的实现(因为它包含一些很好的功能)这里是我试图解决的问题:< / p>

我有一个TabControl,它能够显示多个彼此无关的内容(如浏览器)。 TabControl有一个模板集,为每个要显示的内容创建一个新的区域(所以我有一个NavigationService和每个TabItem的旅程)

<userInterface:TabControlHelper.Template>
    <DataTemplate DataType="{x:Type viewModels:ContentViewModel}">
        <ContentControl x:Name="DataContextProxy">
            <ContentControl prism:RegionManager.RegionName="{Binding ElementName=DataContextProxy, Path=DataContext.(viewModels:ContentViewModel.Id)}"
                            prism:RegionManager.RegionManager="{Binding RelativeSource={RelativeSource AncestorType=views:ContentOverview}, Path=DataContext.RegionManager}"
                            Background="{StaticResource BackgroundBrush}"
                            DataContext="{x:Null}" />
        </ContentControl>
    </DataTemplate>
</userInterface:TabControlHelper.Template>

现在当TabControl.SelectedItem更改为新内容时,我使用以下代码导航到HomeView:

regionManager.Regions[this.SelectedContent.Id].RequestNavigate("HomeView");

导航工作正常,只是ViewModel创建没有: 在我自己的实现中,我处理了导航中的AutoWireViewModel AttachedProperty。所以每当我导航到View我检查它是否已将AutoWireViewModel设置为true,如果我创建了一个ViewModel,我可以使用Region的名称(Content.Id)注入正确的内容

这是我被困的地方。 HomeViewModel需要访问它应显示的当前内容。我知道可以通过NavigationContext注入内容,但HomeViewModel实际上并不关心IContent实例的来源,它只取决于它(它不是可选的,所以我宁愿在via构造函数中传递它)。 HomeView只是需要了解当前内容的很多视图中的一个,这意味着如果我通过NavigationParameters将内容推送到ViewModel中,我需要每次都需要内容的代码,或者我确实需要一些丑陋的基类来处理NavigationParameter并验证它包含一个IContent实例(对我而言似乎是“远距离行动”)。

如何更改Prism Navigation和AutoWireViewModel以自动解析IContent的正确实例? 它应该使用这样的东西:

IContent targetContent = Container.Resolve<IContentManager>.Contents[this.RegionThatDidInvokeTheNavigation.Name]

或者有更好的方法来实现理想的行为吗?

1 个答案:

答案 0 :(得分:2)

我遇到了类似的问题,如果prism稍微修改了它的RegionNavigationService给我们一个影响viewmodel创建的选项,我会很高兴(参见https://github.com/PrismLibrary/Prism/issues/367)。

如果你不想在你的viewmodel上实现INavigationAware(这意味着你在导航实际发生之前就处于未初始化状态),你可以像这样修改RegionNavigationService.ExecuteNavigation:< / p>

[...update journal...]

// Create and set the view model based on the navigation context
var viewAsDependencyObject = view as DependencyObject;
if (viewAsDependencyObject != null)
{
    var createViewModelOnNavigateTo = ViewModelLocator.GetCreateViewModelOnNavigateTo( viewAsDependencyObject );
    if (createViewModelOnNavigateTo)
        ViewModelLocator.Bind( view, _viewModelProvider.CreateViewModel( viewAsDependencyObject, navigationContext ) );
}

[...inform view...]

_viewModelProvider是一种从NavigationContext创建视图模型的服务,CreateViewModelOnNavigate是一个类似于AutoWireViewModel的附加属性。