Wpf 使用 Prism 实战开发Day24

2024-05-26 03:20

本文主要是介绍Wpf 使用 Prism 实战开发Day24,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

自定义询问窗口

当需要关闭系统或进行删除数据或进行其他操作的时候,需要询问用户是否要执行对应的操作。那么就需要一个弹窗来给用户进行提示。

一.添加自定义询问窗口视图 (MsgView.xaml)

1.首先,添加一个自定义询问窗口视图 (MsgView.xaml)

<UserControl x:Class="MyToDo.Views.Dialog.MsgView"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:MyToDo.Views.Dialog"xmlns:md="http://materialdesigninxaml.net/winfx/xaml/themes"mc:Ignorable="d" Width="380" Height="220"><Grid><Grid.RowDefinitions><RowDefinition Height="auto"/><RowDefinition/><RowDefinition Height="auto"/></Grid.RowDefinitions><!--标题--><TextBlock Text="{Binding Title}" d:Text="温馨提示" Padding="5" FontSize="14"/><!--内容--><TextBlock Text="{Binding Content}" d:Text="确认删除该数据吗?" Grid.Row="1" Padding="15,0" FontSize="14" VerticalAlignment="Center"/><!--底部按钮--><StackPanel Grid.Row="2" Margin="10" Orientation="Horizontal" HorizontalAlignment="Right"><Button Content="取消" Margin="0,0,10,0" Style="{StaticResource MaterialDesignOutlinedButton}"Command="{Binding CancelCommand}"/><Button Content="确认" Command="{Binding SaveCommand}"/></StackPanel></Grid>
</UserControl>

2.视图添加完成后,再添加对应的ViewModel,即对应的MsgViewModel 视图逻辑处理类。

 public class MsgViewModel:BindableBase,IDialogHostAware{public MsgViewModel(){CancelCommand = new DelegateCommand(Cancel);SaveCommand = new DelegateCommand(Save);}private string title;public string Title{get { return title; }set { title = value; RaisePropertyChanged(); }}private string content;public string Content{get { return content; }set { content = value; RaisePropertyChanged(); }}public string DialogHostName { get; set; } = "RootDialog";//弹出的子窗口永远赋在父窗口上面public DelegateCommand CancelCommand { get; set; }public DelegateCommand SaveCommand { get; set; }public void OnDialogOpend(IDialogParameters parameters){//接收视图传过来的标题和内容if (parameters.ContainsKey("Title")){Title = parameters.GetValue<string>("Title");}if (parameters.ContainsKey("Content")){Content = parameters.GetValue<string>("Content");}}private void Cancel(){if (DialogHost.IsDialogOpen(DialogHostName)) //是否是打开{DialogHost.Close(DialogHostName, new DialogResult(ButtonResult.No)); //关闭}}private void Save(){if (DialogHost.IsDialogOpen(DialogHostName)) //是否是打开{DialogParameters pairs = new DialogParameters(); //定义返回参数DialogHost.Close(DialogHostName, new DialogResult(ButtonResult.OK, pairs));}}}

3.弹窗视图和对应的处理逻辑添加完毕后,最后一步还需要在App中进行注册

 containerRegistry.RegisterForNavigation<MsgView,MsgViewModel>();

 二.使用自定义询问窗口视图

由于询问窗口视图是多地方复用,因此写成一个扩展方法,供需要使用的地方进行重复调用。

1.添加扩展方法(Question)

 public static class DialogExtensions{/// <summary>/// 发布事件/// </summary>/// <param name="aggregator"></param>/// <param name="model"></param>public static void UpdateLoading(this IEventAggregator aggregator,UpdateModel model){aggregator.GetEvent<UpdateLoadingEvent>().Publish(model);}/// <summary>/// 订阅事件/// </summary>/// <param name="aggregator"></param>/// <param name="model"></param>public static void Resgiter(this IEventAggregator aggregator,Action<UpdateModel> model){aggregator.GetEvent<UpdateLoadingEvent>().Subscribe(model);}/// <summary>/// 询问窗口/// </summary>/// <param name="dialogHost">指定的会话主机</param>/// <param name="title">标题</param>/// <param name="content">内容</param>/// <param name="dialogHostName">会话主机名称</param>/// <returns></returns>public static async Task<IDialogResult> Question(this IDialogHostService dialogHost,string title,string content,string dialogHostName= "RootDialog"){DialogParameters pairs = new DialogParameters();pairs.Add("Title", title);pairs.Add("Content", content);pairs.Add("DialogHostName", dialogHostName);var dialogResult=await dialogHost.ShowDialog("MsgView",pairs,dialogHostName);return dialogResult;}}

2.在需要的询问地方进行使用

例如:在待办事项处理逻辑中使用。首先,在构造函数中注入

在用户删除数据之前,先询问

完整代码

public class ToDoViewModel: NavigationViewModel{//由于NavigationViewModel 类构造中传入了 IOC容器,所以当前类继承的时候,需要把对应的参数传通过Base传过去就不会报错了private readonly IDialogHostService dialogHost;public ToDoViewModel(IToDoService toDoService, IContainerProvider provider):base(provider){ToDoDtos = new ObservableCollection<ToDoDto>();ExecuteCommand = new DelegateCommand<string>(Execute);SelectedCommand = new DelegateCommand<ToDoDto>(Selected);DeleteCommand = new DelegateCommand<ToDoDto>(Delete);dialogHost = provider.Resolve<IDialogHostService>();this.toDoService = toDoService;}private bool isRightDrawerOpen;/// <summary>/// 右侧编辑窗口是否展开/// </summary>public bool IsRightDrawerOpen{get { return isRightDrawerOpen; }set { isRightDrawerOpen = value; RaisePropertyChanged(); }}public DelegateCommand<string> ExecuteCommand{ get; private set; }public DelegateCommand<ToDoDto> SelectedCommand { get; private set; }public DelegateCommand<ToDoDto> DeleteCommand { get; private set; }private ObservableCollection<ToDoDto> toDoDtos;private readonly IToDoService toDoService;/// <summary>/// 创建数据的动态集合/// </summary>public ObservableCollection<ToDoDto> ToDoDtos{get { return toDoDtos; }set { toDoDtos = value;RaisePropertyChanged(); }}private ToDoDto currentDto;/// <summary>/// 编辑选中/新增对象/// </summary>public ToDoDto CurrentDto{get { return currentDto; }set { currentDto = value; RaisePropertyChanged(); }}private string search;/// <summary>/// 用户输入的搜索条件/// </summary>public string Search{get { return search; }set { search = value; RaisePropertyChanged(); }}private int? selectIndex = 0;/// <summary>/// 下拉列表状态值/// </summary>public int? SelectIndex {get { return selectIndex; }set { selectIndex = value; RaisePropertyChanged(); }}/// <summary>/// 获取数据/// </summary>async void GetDataAsync(){UpdateLoading(true); //发布消息,设置加载中的窗口//前端界面 0全部,1 待办,2 已完成;数据库实际值,0待办,1已完成int? stastus=  SelectIndex == 0 ? null : SelectIndex == 2 ? 1 : 0;//添加查询条件var todoResult=await toDoService.GetAllFilterAsync(new Shared.Parameters.ToDoParameter(){PageIndex = 0,PageSize = 100,Search = Search, //传入搜索框查询条件Status= stastus //下拉框值});if (todoResult.Status){toDoDtos.Clear();foreach (var item in todoResult.Result.Items){toDoDtos.Add(item);}}UpdateLoading(false); //发布消息,关闭加载中的窗口}/// <summary>/// 添加待办/// </summary>/// <exception cref="NotImplementedException"></exception>private void Add(){CurrentDto = new ToDoDto();//添加时,初始化一个新对象IsRightDrawerOpen = true;}private async void Save(){//判断数据是否为空if (string.IsNullOrWhiteSpace(CurrentDto.Title) || string.IsNullOrWhiteSpace(CurrentDto.Content)) return;UpdateLoading(true);try{if (CurrentDto.Id > 0) //Id 大于0,表示编辑。否则新增{var updateResult = await toDoService.UpdateAsync(CurrentDto);if (updateResult.Status) //更新成功{//查找到当前界面更新的那个条数据,把显示的内容进行更新var todo = ToDoDtos.FirstOrDefault(t => t.Id == CurrentDto.Id);if (todo != null){todo.Title = CurrentDto.Title;todo.Content = CurrentDto.Content;todo.Status = CurrentDto.Status;}IsRightDrawerOpen = false; //关闭编辑窗口}}else{var addResult = await toDoService.AddAsync(CurrentDto);if (addResult.Status){if(addResult.Result != null){ToDoDtos.Add(addResult.Result); //把数据添加到界面的集合中IsRightDrawerOpen = false; //关闭新增窗口} }}}catch (Exception ex){await Console.Out.WriteLineAsync(ex.Message);}finally{UpdateLoading(false);}}private async void Delete(ToDoDto dto){var dialogResult= await dialogHost.Question("温馨提示",$"确认要删除待办事项:{dto.Title}?");if (dialogResult.Result != ButtonResult.OK) return;var deleteResult=await toDoService.DeleteAsync(dto.Id);if (deleteResult.Status){//在当前数据集合中,找到当前已经删除掉的数据,并移除掉var model= ToDoDtos.FirstOrDefault(t => t.Id.Equals(dto.Id));if(model != null) ToDoDtos.Remove(model);}}/// <summary>/// 根据不同的参数,处理不同的逻辑/// </summary>/// <param name="obj"></param>private void Execute(string obj){switch (obj){case "新增":Add();break;case "查询":GetDataAsync();break;case "保存":Save();break;}}private async void Selected(ToDoDto obj){try{UpdateLoading(true);//进行数据查询var todoResult = await toDoService.GetFirstOfDefaultAsync(obj.Id);if (todoResult.Status){//把拿到的结果,赋给一个当前选中的ToDoDtoCurrentDto = todoResult.Result;IsRightDrawerOpen = true;//打开窗口}}catch (Exception ex){await Console.Out.WriteLineAsync(ex.Message);}finally{UpdateLoading(false);}}//重写导航加载数据的方法public override void OnNavigatedTo(NavigationContext navigationContext){base.OnNavigatedTo(navigationContext);GetDataAsync();}}

3.在视图中使用。退出系统的时候,询问用户

namespace MyToDo.Views
{/// <summary>/// MainView.xaml 的交互逻辑/// </summary>public partial class MainView : Window{public MainView(IEventAggregator aggregator, IDialogHostService dialogHostService){InitializeComponent();//订阅是否打开或关闭加载中的窗口aggregator.Resgiter(arg =>{DialogHost.IsOpen = arg.IsOpen;//设置打开窗口if (DialogHost.IsOpen){DialogHost.DialogContent = new ProgressView();}});//最小化btnMin.Click += (s, e) =>{this.WindowState = WindowState.Minimized;//窗口设置最小};//最大化btnMax.Click += (s, e) =>{//判断窗口是否是最小化状态if (this.WindowState == WindowState.Maximized){this.WindowState = WindowState.Normal; //改成正常状态}else{this.WindowState = WindowState.Maximized;//最大化}};//关闭btnClose.Click += async (s, e) =>{var dialogResult= await  dialogHostService.Question("温馨提示", "确认要退出系统吗?");if (dialogResult.Result != Prism.Services.Dialogs.ButtonResult.OK) return;this.Close();};//鼠标拖动事件ColorZone.MouseMove += (s, e) =>{//如果鼠标在拖动if (e.LeftButton == MouseButtonState.Pressed){this.DragMove();//让窗口移动}};//导航栏双击事件ColorZone.MouseDoubleClick += (s, e) =>{//双击时,如果是窗口是正常形态,就变成最大化if (this.WindowState == WindowState.Normal){this.WindowState = WindowState.Maximized;}else{this.WindowState = WindowState.Normal;//否则就变成正常的形态}};//菜单选择事件menuBar.SelectionChanged += (s, e) =>{drawerHost.IsLeftDrawerOpen = false;};}}
}

这篇关于Wpf 使用 Prism 实战开发Day24的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1003396

相关文章

C语言中联合体union的使用

本文编辑整理自: http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=179471 一、前言 “联合体”(union)与“结构体”(struct)有一些相似之处。但两者有本质上的不同。在结构体中,各成员有各自的内存空间, 一个结构变量的总长度是各成员长度之和。而在“联合”中,各成员共享一段内存空间, 一个联合变量

Tolua使用笔记(上)

目录   1.准备工作 2.运行例子 01.HelloWorld:在C#中,创建和销毁Lua虚拟机 和 简单调用。 02.ScriptsFromFile:在C#中,对一个lua文件的执行调用 03.CallLuaFunction:在C#中,对lua函数的操作 04.AccessingLuaVariables:在C#中,对lua变量的操作 05.LuaCoroutine:在Lua中,

Vim使用基础篇

本文内容大部分来自 vimtutor,自带的教程的总结。在终端输入vimtutor 即可进入教程。 先总结一下,然后再分别介绍正常模式,插入模式,和可视模式三种模式下的命令。 目录 看完以后的汇总 1.正常模式(Normal模式) 1.移动光标 2.删除 3.【:】输入符 4.撤销 5.替换 6.重复命令【. ; ,】 7.复制粘贴 8.缩进 2.插入模式 INSERT

用Microsoft.Extensions.Hosting 管理WPF项目.

首先引入必要的包: <ItemGroup><PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" /><PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" /><PackageReference Include="Serilog

Lipowerline5.0 雷达电力应用软件下载使用

1.配网数据处理分析 针对配网线路点云数据,优化了分类算法,支持杆塔、导线、交跨线、建筑物、地面点和其他线路的自动分类;一键生成危险点报告和交跨报告;还能生成点云数据采集航线和自主巡检航线。 获取软件安装包联系邮箱:2895356150@qq.com,资源源于网络,本介绍用于学习使用,如有侵权请您联系删除! 2.新增快速版,简洁易上手 支持快速版和专业版切换使用,快速版界面简洁,保留主

如何免费的去使用connectedpapers?

免费使用connectedpapers 1. 打开谷歌浏览器2. 按住ctrl+shift+N,进入无痕模式3. 不需要登录(也就是访客模式)4. 两次用完,关闭无痕模式(继续重复步骤 2 - 4) 1. 打开谷歌浏览器 2. 按住ctrl+shift+N,进入无痕模式 输入网址:https://www.connectedpapers.com/ 3. 不需要登录(也就是

React+TS前台项目实战(十七)-- 全局常用组件Dropdown封装

文章目录 前言Dropdown组件1. 功能分析2. 代码+详细注释3. 使用方式4. 效果展示 总结 前言 今天这篇主要讲全局Dropdown组件封装,可根据UI设计师要求自定义修改。 Dropdown组件 1. 功能分析 (1)通过position属性,可以控制下拉选项的位置 (2)通过传入width属性, 可以自定义下拉选项的宽度 (3)通过传入classN

Eclipse+ADT与Android Studio开发的区别

下文的EA指Eclipse+ADT,AS就是指Android Studio。 就编写界面布局来说AS可以边开发边预览(所见即所得,以及多个屏幕预览),这个优势比较大。AS运行时占的内存比EA的要小。AS创建项目时要创建gradle项目框架,so,创建项目时AS比较慢。android studio基于gradle构建项目,你无法同时集中管理和维护多个项目的源码,而eclipse ADT可以同时打开

Toolbar+DrawerLayout使用详情结合网络各大神

最近也想搞下toolbar+drawerlayout的使用。结合网络上各大神的杰作,我把大部分的内容效果都完成了遍。现在记录下各个功能效果的实现以及一些细节注意点。 这图弹出两个菜单内容都是仿QQ界面的选项。左边一个是drawerlayout的弹窗。右边是toolbar的popup弹窗。 开始实现步骤详情: 1.创建toolbar布局跟drawerlayout布局 <?xml vers

Python应用开发——30天学习Streamlit Python包进行APP的构建(9)

st.area_chart 显示区域图。 这是围绕 st.altair_chart 的语法糖。主要区别在于该命令使用数据自身的列和指数来计算图表的 Altair 规格。因此,在许多 "只需绘制此图 "的情况下,该命令更易于使用,但可定制性较差。 如果 st.area_chart 无法正确猜测数据规格,请尝试使用 st.altair_chart 指定所需的图表。 Function signa