WPF-Prism 7.1-导航-母版选项卡控件-模式/对话框窗口

时间:2018-11-17 00:15:20

标签: c# wpf xaml navigation prism

我正在使用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>

3 个答案:

答案 0 :(得分:1)

也许只是找不到您的视图。 第二个参数是否应该是网址而不是字符串? 从这里: 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,我认为您还需要使用“导出”属性标记“视图”。

希望您的问题是您忘记了文件夹之类的东西。

否则,可能与regionmanager无法获得对您所在地区的引用有关。

答案 1 :(得分:1)

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

herethere所述,在这种情况下,您必须在包含该区域的视图的构造函数中手动添加该区域:

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

使用ServiceLocator中的区域经理:

ServiceLocator.Current.GetInstance<IRegionManager>()

答案 2 :(得分:0)

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>

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

对此(有缺陷的)设计的一种可能的改进是创建一种行为,通过编程方式添加这些交互触发器。