当前位置: 首页 > news >正文

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;};}}
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • DA-CLIP论文阅读笔记
  • 如何在VSCode中修改默认终端
  • 如何使用JMeter 进行全链路压测
  • 【Linux取经路】线程同步——条件变量
  • 1、什么是模块化,为什么要模块化?2、衡量模块独立的定性标准是什么?用自己的话表达其含义3、如何理解信息隐藏和局部化?用自己的话或者例子表达其含义
  • JavaScript异步编程:理解和使用Promise、Async/Await
  • Sentinel的授权规则详解
  • 浅析FAT32文件系统
  • 洗地机十大品牌排名:2024十大值得入手的洗地机盘点
  • 高德地图PlaceSearch标记点清除
  • vite+ts+mock+vue-router+pinia实现vue的路由权限
  • C# NetworkStream 流的详解与示例
  • 【Linux学习】深入了解Linux中进程状态及其转换
  • golang中的字节序 binary BigEndian 大端 , LittleEndian 小端 理解与write写入注意事项
  • docker 版 mysql 主从同步
  • 实现windows 窗体的自己画,网上摘抄的,学习了
  • [原]深入对比数据科学工具箱:Python和R 非结构化数据的结构化
  • 【翻译】babel对TC39装饰器草案的实现
  • Cumulo 的 ClojureScript 模块已经成型
  • input实现文字超出省略号功能
  • JS创建对象模式及其对象原型链探究(一):Object模式
  • node和express搭建代理服务器(源码)
  • PHP 程序员也能做的 Java 开发 30分钟使用 netty 轻松打造一个高性能 websocket 服务...
  • php的插入排序,通过双层for循环
  • TiDB 源码阅读系列文章(十)Chunk 和执行框架简介
  • vue自定义指令实现v-tap插件
  • 从零开始学习部署
  • 面试总结JavaScript篇
  • 使用 Node.js 的 nodemailer 模块发送邮件(支持 QQ、163 等、支持附件)
  • 职业生涯 一个六年开发经验的女程序员的心声。
  • 智能合约开发环境搭建及Hello World合约
  • 最近的计划
  • mysql面试题分组并合并列
  • # .NET Framework中使用命名管道进行进程间通信
  • ###51单片机学习(2)-----如何通过C语言运用延时函数设计LED流水灯
  • #git 撤消对文件的更改
  • (1)(1.13) SiK无线电高级配置(五)
  • (3) cmake编译多个cpp文件
  • (附源码)springboot课程在线考试系统 毕业设计 655127
  • (十) 初识 Docker file
  • (十三)Maven插件解析运行机制
  • (一)ClickHouse 中的 `MaterializedMySQL` 数据库引擎的使用方法、设置、特性和限制。
  • (一)Spring Cloud 直击微服务作用、架构应用、hystrix降级
  • (转)【Hibernate总结系列】使用举例
  • (转)德国人的记事本
  • .NET 实现 NTFS 文件系统的硬链接 mklink /J(Junction)
  • .NET 指南:抽象化实现的基类
  • .NET应用架构设计:原则、模式与实践 目录预览
  • .NET中 MVC 工厂模式浅析
  • .net最好用的JSON类Newtonsoft.Json获取多级数据SelectToken
  • /*在DataTable中更新、删除数据*/
  • [Angularjs]asp.net mvc+angularjs+web api单页应用
  • [APIO2012] 派遣 dispatching
  • [Bzoj4722]由乃(线段树好题)(倍增处理模数小快速幂)
  • [C/C++] -- 二叉树