【WPF】Prism P2
一、弹窗设置
Step1 在模块A创建弹窗A和弹窗B,注意,还是要使用【用户控件】
<UserControl x:Class="ModuleA.Views.DialogA"
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:ModuleA.Views"
mc:Ignorable="d"
Height="450" Width="800">
<Grid Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<TextBlock Text="温馨提示" />
<TextBlock VerticalAlignment="Center" Text="这是DialogA" FontSize="30" Grid.Row="1" />
<StackPanel Orientation="Horizontal" Grid.Row="2">
<Button Content="取消" Margin="5" FontSize="15" Command="{ Binding CancelCommand }" />
<Button Content="确定" Margin="5" FontSize="15" Command="{ Binding ConfirmCommand }" />
</StackPanel>
</Grid>
</UserControl>
目录位置:

Step2 创建弹窗A和B对应的视图类,并且该类需要实现IDialogAware接口(仅实例A)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ImTools;
using Prism.Commands;
using Prism.Services.Dialogs;
namespace ModuleA.ViewModels
{
/* 弹窗视图类需要实现 Prism.Services.Dialogs.IDialogAware接口 */
internal class DialogAViewModel : IDialogAware
{
public string Title { get; set; }
public event Action<IDialogResult> RequestClose;
/* 设定弹窗的确认和取消命令 */
public DelegateCommand CancelCommand { get; set; }
public DelegateCommand ConfirmCommand { get; set; }
public DialogAViewModel()
{
/* 命令初始化 */
CancelCommand = new DelegateCommand(cancel);
ConfirmCommand = new DelegateCommand(confirm);
}
/* 设置这个弹窗允许关闭 */
public bool CanCloseDialog()
{
return true;
}
/* 当弹窗关闭时回调方法 */
public void OnDialogClosed()
{
DialogParameters keyValuePairs = new DialogParameters();
keyValuePairs.Add("Value", "Message From DialogA");
RequestClose?.Invoke(new DialogResult(ButtonResult.OK, keyValuePairs));
}
/* 当弹窗打开时回调方法,接受一个参数对象 */
public void OnDialogOpened(IDialogParameters parameters)
{
if (parameters.ContainsKey("Title"))
{
Title = parameters.GetValue<string>("Title");
}
}
/* 确认方法 */
private void confirm()
{
OnDialogClosed();
}
/* 取消方法 */
private void cancel()
{
RequestClose?.Invoke(new DialogResult(ButtonResult.No));
}
}
}
回到模块AProfile类注册弹窗A和B:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ModuleA.ViewModels;
using ModuleA.Views;
using Prism.Ioc;
using Prism.Modularity;
namespace ModuleA
{
public class ModuleAProfile : IModule
{
public void OnInitialized(IContainerProvider containerProvider)
{
}
public void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterForNavigation<ViewD, ViewDViewModel>();
containerRegistry.RegisterDialog<DialogA, DialogAViewModel>();
containerRegistry.RegisterDialog<DialogB, DialogBViewModel>();
}
}
}
MainViewModel类追加弹窗打开方法:
当回调触发时可以接受弹窗信息发送的参数
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Prism.Commands;
using Prism.Mvvm;
using Prism.Regions;
using Prism.Services.Dialogs;
namespace WPF_Prism.ViewModels
{
internal class MainViewModel : BindableBase
{
public DelegateCommand<string> OpenCommand { private set; get; }
public DelegateCommand BackCommand { private set; get; }
public DelegateCommand<string> OpenDialogCommand { private set; get; }
private readonly IRegionManager regionManager;
private readonly IDialogService dialogService;
private IRegionNavigationJournal journal;
/* 初始化时通过构造器注入区域管理器对象 */
public MainViewModel(IRegionManager regionManager, IDialogService dialogService)
{
/* 命令逻辑初始化 */
OpenCommand = new DelegateCommand<string>(Open);
BackCommand = new DelegateCommand(Back);
OpenDialogCommand = new DelegateCommand<string> (OpenDialog);
/* 初始化Prism资源 */
this.regionManager = regionManager;
this.dialogService = dialogService;
}
private void Open(string obj)
{
/* 可以向路由传递参数 */
NavigationParameters keys = new NavigationParameters();
keys.Add("Title", "nav-para");
/* 通过区域管理器对象,指定区域名获取该区域对象,并导航到目标视图控件对象上 */
regionManager.Regions["ContentRegion"].RequestNavigate(obj, navigationCallback =>
{
if (journal == null && (bool)navigationCallback.Result)
journal = navigationCallback.Context.NavigationService.Journal;
}, keys);
}
private void Back()
{
if (journal != null && journal.CanGoBack)
{
journal.GoBack();
}
}
/* 弹窗打开方法 */
private void OpenDialog(string obj)
{
/* 调用弹窗展示方法之前可以传递参数信息 */
DialogParameters keyValuePairs = new DialogParameters();
keyValuePairs.Add("Title", obj);
/* 在该弹窗关闭之后可以回调处理逻辑 */
dialogService.ShowDialog(obj, keyValuePairs, callback =>
{
/* 当为确认时再处理逻辑 */
if (callback.Result == ButtonResult.OK)
{
string result = callback.Parameters.GetValue<string>("Value");
Console.WriteLine(result);
}
});
}
}
}
主窗口xaml追加弹窗按钮支持:
<Window x:Class="WPF_Prism.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:WPF_Prism"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<Button Margin="5" Command="{ Binding OpenCommand }" CommandParameter="ViewA">ViewA</Button>
<Button Margin="5" Command="{ Binding OpenCommand }" CommandParameter="ViewB">ViewB</Button>
<Button Margin="5" Command="{ Binding OpenCommand }" CommandParameter="ViewC">ViewC</Button>
<Button Margin="5" Command="{ Binding OpenCommand }" CommandParameter="ViewD">ViewD</Button>
<Button Margin="5" Command="{ Binding OpenCommand }" CommandParameter="ViewE">ViewE</Button>
<Button Margin="5" Command="{ Binding BackCommand }">上一页</Button>
</StackPanel>
<StackPanel Grid.Row="1" Orientation="Horizontal">
<Button Margin="5" Command="{ Binding OpenDialogCommand }" CommandParameter="DialogA">DialogA</Button>
<Button Margin="5" Command="{ Binding OpenDialogCommand }" CommandParameter="DialogB">DialogB</Button>
</StackPanel>
<ContentControl Grid.Row="2" prism:RegionManager.RegionName="ContentRegion" />
</Grid>
</Window>
执行预览:

关闭时参数接收的Debug调试

二、事件订阅与发布
在模块A中新建event目录,并添加MessageEvent类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DryIoc.Messages;
using Prism.Events;
namespace ModuleA.Event
{
/* 定义一般string的消息事件类 */
public class MessageEvent : PubSubEvent<string>
{
}
/* 定义业务数据实体的消息事件类 */
public class BusEvent : PubSubEvent<BusData>
{
}
public class BusData
{
private int _id;
private string _code;
private string _message;
public int Id { get { return _id; } set { _id = Id; } }
public string Code { get { return _code; } set { _code = Code; } }
public string Message { get { return _message; } set { _message = Message; } }
}
}
在弹窗A的类的构造器参数中追加事件聚合器接口:
聚合器根据泛型获取对应的事件对象,并调用订阅回调方法
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using ModuleA.Event;
using Prism.Events;
namespace ModuleA.Views
{
/// <summary>
/// DialogA.xaml 的交互逻辑
/// </summary>
public partial class DialogA : UserControl
{
public DialogA(IEventAggregator eventAggregator)
{
InitializeComponent();
eventAggregator.GetEvent<MessageEvent>().Subscribe(arg =>
{
MessageBox.Show($"接收到消息:{arg}");
});
}
}
}
弹窗A的视图类,在初始化时发布消息:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ImTools;
using ModuleA.Event;
using Prism.Commands;
using Prism.Events;
using Prism.Services.Dialogs;
namespace ModuleA.ViewModels
{
/* 弹窗视图类需要实现 Prism.Services.Dialogs.IDialogAware接口 */
internal class DialogAViewModel : IDialogAware
{
public string Title { get; set; }
public event Action<IDialogResult> RequestClose;
/* 设定弹窗的确认和取消命令 */
public DelegateCommand CancelCommand { get; set; }
public DelegateCommand ConfirmCommand { get; set; }
public DialogAViewModel(IEventAggregator eventAggregator)
{
/* 命令初始化 */
CancelCommand = new DelegateCommand(cancel);
ConfirmCommand = new DelegateCommand(confirm);
eventAggregator.GetEvent<MessageEvent>().Publish("Hello");
}
/* 设置这个弹窗允许关闭 */
public bool CanCloseDialog()
{
return true;
}
/* 当弹窗关闭时回调方法 */
public void OnDialogClosed()
{
DialogParameters keyValuePairs = new DialogParameters();
keyValuePairs.Add("Value", "Message From DialogA");
RequestClose?.Invoke(new DialogResult(ButtonResult.OK, keyValuePairs));
}
/* 当弹窗打开时回调方法,接受一个参数对象 */
public void OnDialogOpened(IDialogParameters parameters)
{
if (parameters.ContainsKey("Title"))
{
Title = parameters.GetValue<string>("Title");
}
}
/* 确认方法 */
private void confirm()
{
OnDialogClosed();
}
/* 取消方法 */
private void cancel()
{
RequestClose?.Invoke(new DialogResult(ButtonResult.No));
}
}
}
执行效果:
先触发消息订阅回调,之后再打开弹窗

三、MaterialDesign UI库
地址:https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit
发现直接打开项目无法运行:

错误代码是:NETSDK1141
定位到项目的global.json文件

打开发现要求dotnet版本是8.0.100

但是我在vs的设置里面查看了已经安装的dotnet环境库

可以发现已经安装了8.0的环境

然后查看本地DotNet环境时发现使用的版本是9.0.100
命令: dotnet --info

所以猜想是因为global.json的版本和本地环境不一致导致,将global.json改为9.0.100版本

保存后项目启动正常...

可以打包发布出来,里面有组件的演示案例:

四、MD UI库引入到项目
1、NUGET包管理找到 MD主题资源并下载:
搜素关键字:MaterialDesignThemes

2、在App.xaml中,追加关于MD的资源引用
注意这里不要使用MD官方的,需要改用视频地址里的资源引用方式
<prism:PrismApplication x:Class="NoteApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:NoteApp"
xmlns:prism="http://prismlibrary.com/"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<materialDesign:BundledTheme BaseTheme="Dark" PrimaryColor="DeepPurple" SecondaryColor="Lime" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</prism:PrismApplication>
3、在主窗口编写一个按钮,测试样式是否有效
<Window x:Class="NoteApp.MainWindow"
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:NoteApp"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition />
</Grid.RowDefinitions>
<Button Content="hello" Height="50" />
</Grid>
</Window>
启动后预览展示:


浙公网安备 33010602011771号