Prism弹窗

创建弹窗

创建弹窗内容

创建一个弹出窗口的内容:一般是UserControl(不是Window)

<UserControl x:Class="Zhaoxi.PrismDialog.UCDetail"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:Zhaoxi.PrismDialog"
             xmlns:p="http://prismlibrary.com/"
             mc:Ignorable="d"  FontSize="20" Foreground="Orange"
             d:DesignHeight="450" d:DesignWidth="800"
             Height="300" Width="500">
    <p:Dialog.WindowStyle>
        <Style TargetType="Window">
            <Setter Property="Width" Value="500"/>
            <Setter Property="Height" Value="300"/>
            <Setter Property="WindowChrome.WindowChrome">
                <Setter.Value>
                    <WindowChrome GlassFrameThickness="-1"/>
                </Setter.Value>
            </Setter>
        </Style>
    </p:Dialog.WindowStyle>
    <StackPanel>
        <TextBlock Text="弹出窗口内容"/>
        <TextBox Text="{Binding Value,UpdateSourceTrigger=PropertyChanged}"/>
        <Button Content="Close" Command="{Binding CloseCommand}"/>
    </StackPanel>
</UserControl>

使用Prism框架提供的Dialog.WindowStyle属性,修改窗体的样式

在UserControl中设置Height和Width属性,修改弹窗的初始大小

注册弹窗

对应的ViewModel实现IDialogAware接口

    public partial class UCDetail : UserControl
    {
        public UCDetail(IContainerProvider containerProvider)
        {
            InitializeComponent();
            this.DataContext = new DetailViewModel();
        }
    }
public class DetailViewModel : BaseVM, IDialogAware
    {
        // 弹出窗口的标题
        public string Title => "Hello Dialog";

        // 执行关闭返回
        public event Action<IDialogResult> RequestClose;

        // 当前打开的窗口是否允许关闭
        public bool CanCloseDialog()
        {
            return true;
        }

        // 当弹出窗口关闭时执行的逻辑
        public void OnDialogClosed()
        {

        }

        // 当弹出窗口打开的时候执行的逻辑
        public void OnDialogOpened(IDialogParameters parameters)
        {
 
        }
    }

 在RegisterTypes方法中注册弹窗

    public partial class App : PrismApplication
    {
        protected override Window CreateShell()
        {
            return Container.Resolve<MainWindow>();
        }

        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            // 注册弹窗内容
            containerRegistry.RegisterDialog<UCDetail>("AAAA");
        }
    }

调用弹窗

注入IDialogService,使用ShowDialog方法调用弹窗

public MainViewModel(IEventAggregator eventAggregator, IDialogService dialogService)
{
    _dialogService = dialogService;
     OpenCommand = new DelegateCommand(OnOpen);
}

public DelegateCommand OpenCommand { get; set; }

private void OnOpen()
{
    //每次打开都是新的实例
    _dialogService.ShowDialog("AAAA");
}

创建弹窗窗口

对应的Window的窗口需要实现IDialogWindow接口

    public partial class DialogParent : Window, IDialogWindow
    {
        public DialogParent()
        {
            InitializeComponent();
        }

        public IDialogResult Result { get; set; }
    }

修改弹窗窗口样式

Title改为绑定

<Window x:Class="Zhaoxi.PrismDialog.DialogParent"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Zhaoxi.PrismDialog"
        mc:Ignorable="d"  SizeToContent="WidthAndHeight"
        
        Title="{Binding Title}" Height="450" Width="800">
    <Window.Template>
        <ControlTemplate TargetType="Window">
            <Border CornerRadius="10" Background="Orange" Margin="5">
                <Border.Effect>
                    <DropShadowEffect BlurRadius="10" Color="Gray" ShadowDepth="0" Opacity="0.3"/>
                </Border.Effect>
                <ContentPresenter/>
            </Border>
        </ControlTemplate>
    </Window.Template>

</Window>

RegisterTypes中注册弹窗窗口即可

public partial class App : PrismApplication
 {
     protected override Window CreateShell()
     {
         return Container.Resolve<MainWindow>();
     }

     protected override void RegisterTypes(IContainerRegistry containerRegistry)
     {
         // 注册弹窗内容
         containerRegistry.RegisterDialog<UCDetail>("AAAA");
         // 注册弹窗窗口,这句代码会将框架内的默认弹窗窗口替换掉
         //弹窗窗体别名"fwefewfe",可以不填默认RegisterDialogWindow中填入的泛型名称-"DialogParent"
         containerRegistry.RegisterDialogWindow<DialogParent>("fwefewfe");
     }
 }
// 4、可以根据注册Dialog窗口的名称,使用特定的窗口对象
// 注册的窗口名称,如果指定了,在容器中必须存在这个名称的
// 否则报错:Exception:No registered type IDialogWindow with the key fwefewfe.
_dialogService.ShowDialog("AAAA", param, OnDialogClosed, "fwefewfe");

弹窗参数请求

弹窗传进参数

使用IDialogService提供的ShowDialog方法实现参数拆传递

// 摘要:
//     Shows a modal dialog.
//     显示模式对话框
// 参数:
//   name:
//     The name of the dialog to show.
//     要显示的对话框的名称。
//   parameters:
//     The parameters to pass to the dialog.
//     要传递给对话框的参数。
//   callback:
//     The action to perform when the dialog is closed.
//     对话框关闭时要执行的操作。
void ShowDialog(string name, IDialogParameters parameters, Action<IDialogResult> callback);

创建DialogParameters对象,并加入参数体

param.Add(参数名称, 参数内容)

private void OnOpen()
{
    DialogParameters param = new DialogParameters();
    param.Add("svsdvsf", "Hello Dialog");
    _dialogService.ShowDialog("AAAA", param, OnDialogClosed);
}

private void OnDialogClosed(IDialogResult result)
{
    
}

 弹窗对应的ViewModel中取出参数

// 当弹出窗口打开的时候执行的逻辑
public void OnDialogOpened(IDialogParameters parameters)
{
    string arg = parameters.GetValue<string>("svsdvsf");
}

弹窗返回参数

DialogResult创建对象,并加入参数体

触发IDialogAware提供的事件RequestClose触发回调,调用_dialogService.ShowDialog("AAAA", param, OnDialogClosed)中OnDialogClosed方法体

public DelegateCommand CloseCommand { get; set; }
public DetailViewModel()
{
    CloseCommand = new DelegateCommand(OnClose);
}
private void OnClose()
{
    IDialogResult dialogResult = new DialogResult();
    dialogResult.Parameters.Add("A", true);
    RequestClose?.Invoke(dialogResult);
}

弹窗中的区域注册

编写三个页面测试

MainView页面打开弹窗

<Window x:Class="Zhaoxi.PrismRegion.NewRegion.Views.MainView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Zhaoxi.PrismRegion.NewRegion.Views"
        xmlns:p="http://prismlibrary.com/"
        mc:Ignorable="d" FontSize="20"
        Title="MainView" Height="450" Width="800">
    <Grid>
        <ContentControl p:RegionManager.RegionName="MainRegion"/>
        <Button Content="打开弹窗" Command="{Binding ShowDialogCommand}"/>
    </Grid>
</Window>

DialogView页面命名一个区域和加载区域的Command

ViewModel继承IDialogAware接口,初始化的时初始化DelegateCommand

<UserControl x:Class="Zhaoxi.PrismRegion.NewRegion.Views.DialogView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:Zhaoxi.PrismRegion.NewRegion.Views"
             xmlns:p="http://prismlibrary.com/"
             mc:Ignorable="d"  FontSize="20"
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <Button Content="加载页面" Command="{Binding ShowViewCommand}"
                VerticalAlignment="Top"/>
        <ContentControl p:RegionManager.RegionName="DialogRegion"
                        Margin="0,30,0,0"/>
    </Grid>
</UserControl>
public class DialogViewModel : IDialogAware
{
    public string Title => "";

    public event Action<IDialogResult> RequestClose;

    public bool CanCloseDialog()
    {
        return true;
    }

    public void OnDialogClosed()
    {

    }

    public void OnDialogOpened(IDialogParameters parameters)
    {

    }

    public DelegateCommand ShowViewCommand { get; set; }
     
    public DialogViewModel(IRegionManager regionManager)
    {
        ShowViewCommand = new DelegateCommand(() =>
        {     
            // 打开SubView
            regionManager.RequestNavigate("DialogRegion", "SubView");
        });
    }
}

运行后点击加载页面后显示失败

查看regionManager的属性发现只有MainView的MainRegion区域被注册

因为Prism框架会默认扫描CreateShell方法返回的窗体区域进行注册,但弹窗是后续初始化,并不会注册区域所以显示失败

在DialogView初始哈的时候注入IRegionManager

注册区域:RegionManager.SetRegionManager(this, regionManager);

刷新区域:RegionManager.UpdateRegions();

订阅弹窗的Unloaded事件,弹窗关闭时移除注册区域防止下次初始化时报错:区域已注册

/// <summary>
/// DialogView.xaml 的交互逻辑
/// </summary>
public partial class DialogView : UserControl
{
    public DialogView(IRegionManager regionManager)
    {
        InitializeComponent();

        RegionManager.SetRegionManager(this, regionManager);
        RegionManager.UpdateRegions();

        this.Unloaded += DialogView_Unloaded;
    }

    private void DialogView_Unloaded(object sender, RoutedEventArgs e)
    {
        var rm = RegionManager.GetRegionManager(this);
        rm.Regions.Remove("DialogRegion");
    }
}

运行后,regionManager中注册有两个区域

加载成功

posted @ 2023-12-07 13:42  ZHIZRL  阅读(211)  评论(0编辑  收藏  举报