WPF - Prism 7.1 - 导航 - 掌握选项卡控件 - 模态/对话框窗口

Posted

技术标签:

【中文标题】WPF - Prism 7.1 - 导航 - 掌握选项卡控件 - 模态/对话框窗口【英文标题】:WPF - Prism 7.1 - Navigation - Mastering Tab Control - Modal/Dialog Window 【发布时间】:2019-04-20 04:21:38 【问题描述】:

我正在使用 Prism 7.1 导航框架 (WPF) 使用以下配置弹出一个对话框窗口。这是成功的。但是,我希望此弹出窗口具有可以在其中来回导航的选项卡。当我单击弹出框上的按钮以尝试在其中显示 ViewA 时,没有任何反应。通过设置断点,我看到导航路径被命中,并且正在显示正确的视图名称。请参阅 PopUpWindow.cs。但是,当它解析视图时,视图不会显示。更糟糕的是,没有抛出错误!我很困惑为什么会发生这种情况。

假设我的命名空间是正确的,我做错了什么?

PrismApplication.cs

protected override void RegisterTypes(IContainerRegistry containerRegistry)

    containerRegistry.RegisterForNavigation<ViewA>();


//Have tried register type, register type for navigation, etc etc.

MainWindowViewModel.xaml

<Window 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        xmlns:prism="http://prismlibrary.com/"
        prism:ViewModelLocator.AutoWireViewModel="True"
        Height="350" Width="525">
    <i:Interaction.Triggers>
        <prism:InteractionRequestTrigger SourceObject="Binding NotificationRequest">
            <prism:PopupWindowAction IsModal="True" CenterOverAssociatedObject="True" />
        </prism:InteractionRequestTrigger>
    </i:Interaction.Triggers>
    <StackPanel>
        <Button Margin="5" Content="Raise Default Notification" Command="Binding NotificationCommand" />
    </StackPanel>

MainWindowViewModel.cs

public MainWindowViewModel

    public InteractionRequest<INotification> NotificationRequest  get; set; 
    public DelegateCommand NotificationCommand  get; set; 

    public MainWindowViewModel()
    
        NotificationRequest = new InteractionRequest<INotification>();
        NotificationCommand = new DelegateCommand(RaiseNotification);
    

    void RaiseNotification()
    
        NotificationRequest.Raise(new PopupWindow());
    

PopUpWindow.xaml

<UserControl 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:prism="http://prismlibrary.com/"
        prism:ViewModelLocator.AutoWireViewModel="True"
        Height="350" Width="525">
    <DockPanel LastChildFill="True">
        <StackPanel Orientation="Horizontal" DockPanel.Dock="Top" Margin="5" >
            <Button Command="Binding NavigateCommand" CommandParameter="ViewA" Margin="5">Navigate to View A</Button> 
        </StackPanel>
        <ContentControl prism:RegionManager.RegionName="ContentRegion" Margin="5"  />
    </DockPanel>
</UserControl>

PopUpWindow.cs

public class PopupWindowViewModel

    private readonly IRegionManager _regionManager;

    public DelegateCommand<string> NavigateCommand  get; private set; 

    public PopupWindowViewModel(IRegionManager regionManager)
    
        _regionManager = regionManager;

        NavigateCommand = new DelegateCommand<string>(Navigate);
    

    private void Navigate(string navigatePath)
    
        if (navigatePath != null)
            _regionManager.RequestNavigate("ContentRegion", navigatePath); 

        //During debugging, this correctly shows navigatePath as "ViewA"
    

ViewA.xaml

<UserControl 
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:prism="http://prismlibrary.com/"             
             prism:ViewModelLocator.AutoWireViewModel="True">
    <Grid>
        <TextBlock Text="ViewA" FontSize="48" HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Grid>
</UserControl>

【问题讨论】:

您使用的是 xamarin 表单吗? RegisterForNavigation 是 Xamarin 表单中导航的注册方法,而不是文档中的 wpf。 根据 Brians Prism 7.1 示例,它对 WPF 也有效(当然他的示例在模块中,而不是在主引导程序中)github.com/PrismLibrary/Prism-Samples-Wpf/blob/master/… 【参考方案1】:

也许只是没有找到您的观点。 第二个参数不应该是 url 而不是字符串吗? 从这里: https://prismlibrary.github.io/docs/wpf/Navigation.html

    IRegionManager regionManager = ...;
regionManager.RequestNavigate("MainRegion",
                                new Uri("InboxView", UriKind.Relative));

检查您的视图在哪里以及路径应该是什么。 我认为你可以证明使用类似的东西:

var testinstance = System.Windows.Application.LoadComponent(testUrl);

https://docs.microsoft.com/en-us/dotnet/api/system.windows.application.loadcomponent?view=netframework-4.7.2

如果您使用的是 MEF,我认为您还需要使用 Export 属性标记视图。

希望你的问题只是你忘记了一个文件夹或类似的东西。

如果不是,则可能与 regionmanager 没有获得对您所在地区的引用有关。

【讨论】:

【参考方案2】:

区域管理器会忽略不在可视化树中的区域。您在PopUpWindow(延迟创建)中定义了ContentRegion,因此它不存在,并且对未知区域的导航请求将被忽略。

正如here 和there 所详述,在这种情况下,您必须在包含它的视图的构造函数中手动添加该区域:

RegionManager.SetRegionName( theNameOfTheContentControlInsideThePopup, WellKnownRegionNames.DataFeedRegion );
RegionManager.SetRegionManager( theNameOfTheContentControlInsideThePopup, theRegionManagerInstanceFromUnity );

与来自ServiceLocator 的区域经理:

ServiceLocator.Current.GetInstance<IRegionManager>()

【讨论】:

【参考方案3】:

InteractionRequest 模式有点古怪。您需要确保应对请求做出反应的所有视图在可视化树中都具有必要的InteractionRequestTrigger。因此,立即解决您的问题的方法是将您的 XAMLMainWindowView.xaml 复制到 ViewA.xaml

<UserControl 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:prism="http://prismlibrary.com/"
        prism:ViewModelLocator.AutoWireViewModel="True"
        Height="350" Width="525">
   <i:Interaction.Triggers>
        <prism:InteractionRequestTrigger SourceObject="Binding NotificationRequest">
            <prism:PopupWindowAction IsModal="True" CenterOverAssociatedObject="True" />
        </prism:InteractionRequestTrigger>
    </i:Interaction.Triggers> 
    <!-- ... -->
</UserControl>

然后确保在 ViewA 的视图模型中添加 NotificationRequest。请注意,您可能仍会遇到交互请求不起作用的情况。例如。在数据模板添加触发器时。不过,只要将它们放在UserControl 级别上就可以了。

对这种(有缺陷的)设计的一个可能改进是创建一种行为,您可以在其中以编程方式添加这些交互触发器。

【讨论】:

以上是关于WPF - Prism 7.1 - 导航 - 掌握选项卡控件 - 模态/对话框窗口的主要内容,如果未能解决你的问题,请参考以下文章

从PRISM开始学WPF导航Navigation?

.NET Core 3 WPF MVVM框架 Prism系列之导航系统

Prism/MVVM (MEF/WPF):从模块中公开导航 [例如菜单]

PRISM WPF - 导航每次都会创建新视图

使用Prism 7.1,x在UnityContainer中注册模拟对象以进行单元测试

01Prism WPF 入门实战 - 项目准备