棱镜6导航并动态发现视图

时间:2017-10-20 16:33:35

标签: c# wpf mvvm prism

我正在使用Prism 6来构建具有多个不同模块的应用程序。这是一个简单的按钮菜单,每个按钮都将主要内容区域导航到不同的动态发现视图。不幸的是,我发现自己硬编码主菜单按钮显然不是我想要的。

我想要的是从已注册我的类别的所有视图的列表中动态构建单选按钮的ItemsControl。但我无法弄清楚如何编写ViewModel属性,要求Prism提供这样的列表

此外,我希望能够保证我的整体方法是合理的。

为了说明,现在我有几个功能显示器,每个都在自己的模块中实现。

  • 用于显示来自相机的实时视图和捕获图像的模块
  • 用于浏览捕获图像库的模块
  • 其他因简洁而被忽略

在我的主视图XAML中,我在左侧的DockPanel中有按钮,在右侧有一个区域中的视图内容(ContentControl“Main”)。这是XAML稍微减少了一点。

    <DockPanel >
    <Border MinWidth="50"
            DockPanel.Dock="Left"
            >
        <StackPanel Orientation="Vertical">
            <StackPanel.Resources>
                <Style TargetType="{x:Type RadioButton}"
                       BasedOn="{StaticResource CategoryButton}">
                    <Setter Property="GroupName" Value="MainGroup"/>
                    <Setter Property="IsChecked">
                        <Setter.Value>
                        <MultiBinding Converter="{StaticResource ObjectEqualsConverter}" Mode="OneWay">
                            <Binding Path="DataContext.ActivePageName" 
                                     RelativeSource="{RelativeSource AncestorType={x:Type Window}}" />
                            <Binding Path="CommandParameter" RelativeSource="{RelativeSource Self}"  />
                        </MultiBinding>
                        </Setter.Value>
                    </Setter>
                </Style>
            </StackPanel.Resources>
            <RadioButton Command="{Binding NavigateCmd}" 
                         CommandParameter="CaptureView"
                         Margin="5"  Content="Capture"
            />

            <RadioButton Command="{Binding NavigateCmd}" 
                         CommandParameter="LibraryView"
                         Margin="5"   Content="Explore" 
            />

        </StackPanel>
    </Border>

    <!--
    Content is in the region named "Main".  Modules register their own page 
    views and we navigate this region to show them as the user clicks the
    page buttons.  
    -->
    <ContentControl x:Name="Page" 
                    prism:RegionManager.RegionName="{x:Static ga:Regions.Main}"
                    />
</DockPanel>

</Window>

我的主视图模型

    public class MainWindowVm : BaseVm
{
    private readonly IRegionManager _regionManager;
    private readonly IUnityContainer _container;
    private readonly IModuleCatalog _catalog;
    private readonly IEventAggregator _aggregator;
    public MainWindowVm(
        IRegionManager rm, 
        IUnityContainer container, 
        IModuleCatalog catalog)
    {
        NavigateCmd = new Prism.Commands.DelegateCommand<string>(Navigate);

        _regionManager = rm;
        _container = container;
        _catalog = catalog;
    }

    public string CurrentView => (string)_regionManager?.Regions[Regions.Main]?.ActiveViews?.FirstOrDefault()?.ToString() ?? "";
    public Prism.Commands.DelegateCommand<string> NavigateCmd { get; private set; }
    public void Navigate(string path)
    {
        _regionManager.RequestNavigate(Regions.Main, path, NavigationCompleted);
    }



    private void NavigationCompleted(NavigationResult nr)
    {
        RaisePropertyChanged("");
    }

    public string ActivePageName
    {
        get
        {
            // HACK:  Currently I'm taking the fully qualified name of the
            // current view (e.g. "MyCompany.LibraryModule.LibraryView") and just
            // chopping off all namespaces to get the basic, unqualified 
            // view name (e.g. "LibraryView") which I am blithely assuming 
            // will perfectly match one of the Page buttons on the main 
            // window.  This really needs to be improved and generalized...

            var name = CurrentView;
            var i = name.LastIndexOf('.');
            if (-1 != i)
                name = name.Substring(i+1);

            return name;
        }
    }  
};

我的模块使用RegisterTypeForNavigation注册他们的视图。例如:

public class LibraryModule : IModule
{
    private readonly IRegionManager _regionManager;
    private readonly IUnityContainer _container;

    public LibraryModule(IRegionManager regionManager, IUnityContainer c)
    {
        _regionManager = regionManager;
        _container = c;
    }

    public void Initialize()
    {
        _container.RegisterTypeForNavigation<LibraryView>();
    }
}

根据我的设置,是否有一种简单的方法可以实现这一点。我应该使用其他一些注册/导航方法吗?

Prism变化如此剧烈,所有样本似乎都有点过时,所以我不知道该怎么做

1 个答案:

答案 0 :(得分:1)

  

Prism变化如此剧烈,所有样本似乎都有点过时,所以我不知道该怎么做

实际上,WPF的棱镜多年来没有变化,所有当前的样品都是最新的。所以,不确定你的基础是什么。

你正在考虑这一切都错了。您正在注册您的视图,然后尝试询问Prism视图名称是什么。相反,实际发生的是你告诉Prism你有什么视图名称并相应地注册。您已经拥有了数据,只需将其存储在您可以要求的位置即可。您可能最好使用某种类型的ViewRegistrationService来管理注册的视图名称,并将它们添加到ItemsControl可以绑定到的集合中。该服务应该是一个单身人士。