Wpf 使用 Prism 实战开发Day24

news2024/12/26 22:23:19

自定义询问窗口

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

一.添加自定义询问窗口视图 (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)
             {
                 //把拿到的结果,赋给一个当前选中的ToDoDto
                 CurrentDto = 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;
            };
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1693441.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何在 Jupyter Notebook 中切换/使用 conda 虚拟环境?

参考文章&#xff1a; 【最全指南】如何在 Jupyter Notebook 中切换/使用 conda 虚拟环境&#xff1f;_多个conda环境 notebook用的哪个-CSDN博客 感谢这篇文章博主的解答&#xff0c;成功解决了我的难题。以下做一些具体的操作方法以及心得体会&#xff1a; 这里我使用的这篇…

meshshader中对三角形的组织优化

一、Mesh Shader与Index Buffer压缩 1. Mesh Shader简介 Mesh Shader是一种新型的图形着色器&#xff0c;结合了传统的顶点着色器和几何着色器的功能&#xff0c;提供了更高的灵活性和性能。它允许开发者以更自由的方式组织和处理顶点数据&#xff0c;从而优化渲染流程。 2.…

【C语言深度解剖】(15):动态内存管理和柔性数组

&#x1f921;博客主页&#xff1a;醉竺 &#x1f970;本文专栏&#xff1a;《C语言深度解剖》 &#x1f63b;欢迎关注&#xff1a;感谢大家的点赞评论关注&#xff0c;祝您学有所成&#xff01; ✨✨&#x1f49c;&#x1f49b;想要学习更多C语言深度解剖点击专栏链接查看&…

螺旋矩阵的思想

方阵类型 https://leetcode.cn/problems/spiral-matrix-ii/ lc59: 螺旋矩阵&#xff0c; 解题思路 关键点&#xff1a; 上方&#xff0c; 从左到右&#xff1b; 右侧&#xff0c;从上到下&#xff1b; 下方&#xff0c;从右到左&#xff1b; 左侧&#xff0c; 从下往上&…

c语言:将小写字母转换为大写字母

//将小写字母转换为大写字母 #include <stdio.h> #include <ctype.h> int main() { char arr[]"you are low"; int i0; while(arr[i]) { if(islower(arr[i])) { arr[i]arr[i]-32; } i; } printf("%s\n",arr); return 0; }

iCloud 照片到 Android 指南:帮助您快速将照片从 iCloud 传输到安卓手机

​ 概括 iOS 和 Android 之间的传输是一个复杂的老问题。将 iCloud 照片传输到 Android 似乎是不可能的。放心。现在的高科技已经解决了这个问题。尽管 Apple 和 Android 不提供传输工具&#xff0c;但您仍然有其他有用的选项。这篇文章与您分享了 5 个技巧。因此&#xff0c;…

Vue3实战笔记(42)—Vue + ECharts:流量数据可视化的强大组合

文章目录 前言vue3使用echarts标准demo&#xff1a;总结 前言 在前端开发中&#xff0c;数据可视化已经成为了一个不可或缺的部分。Vue.js作为一个轻量级且易于上手的渐进式JavaScript框架&#xff0c;与ECharts这个强大的数据可视化库的结合&#xff0c;使得在Vue应用中构建交…

【30天精通Prometheus:一站式监控实战指南】第8天:redis_exporter从入门到实战:安装、配置详解与生产环境搭建指南,超详细

亲爱的读者们&#x1f44b;   欢迎加入【30天精通Prometheus】专栏&#xff01;&#x1f4da; 在这里&#xff0c;我们将探索Prometheus的强大功能&#xff0c;并将其应用于实际监控中。这个专栏都将为你提供宝贵的实战经验。&#x1f680;   Prometheus是云原生和DevOps的…

散列(哈希)及其练习题(基础)

目录 散列 字符出现次数 力扣经典题&#xff1a;两数之和 集合运算 交 并 差 字符串的出现次数 散列 导入&#xff1a; 有N个数和M个数&#xff0c;如何判断M个数中每个数是否在N中出现&#xff1f; 思想&#xff1a;空间换时间 创建hashtable&#xff0c;以N个数本…

【Linux】信号>信号产生信号处理信号保存信号详解

主页&#xff1a;醋溜马桶圈-CSDN博客 专栏&#xff1a;Linux_醋溜马桶圈的博客-CSDN博客 gitee&#xff1a;mnxcc (mnxcc) - Gitee.com 目录 1.信号入门 1.1 生活角度的信号 1.2 技术应用角度的信号 1.3 信号概念 1.4 信号处理常见方式概览 2.产生信号 2.1 通过终端按键…

mac远程桌面连接工具:Microsoft Remote Desktop正式版

Microsoft Remote Desktop 是一款由微软开发的远程桌面控制软件。它允许用户通过互联网连接到远程计算机&#xff0c;从而可以在本地计算机上访问和控制远程计算机的桌面、文件和应用程序。 下载地址&#xff1a;https://www.macz.com/mac/1004.html?idOTI2NjQ5Jl8mMjcuMTg2Lj…

为了性能,放弃tft_eSPI,选择arduino_gfx吧

本来对于tft_espi和arduino_gfx没啥特别的感觉&#xff0c;都是tft屏幕驱动,arduino_gfx的好处就是除了支持tft外还支持一些oled屏幕。 谁知道在探寻我那个在单片机项目上显示中文方案 https://github.com/StarCompute/tftziku 时候&#xff0c;寻求极致性能测了一些东西。 t…

Kiwi浏览器 - 支持 Chrome 扩展的安卓浏览器

​【应用名称】&#xff1a;Kiwi浏览器 - 支持 Chrome 扩展的安卓浏览器 ​【适用平台】&#xff1a;#Android ​【软件标签】&#xff1a;#Kiwi ​【应用版本】&#xff1a;124.0.6327.2 ​【应用大小】&#xff1a;233MB ​【软件说明】&#xff1a;一款基于开源项目 Chr…

每日一题 求和

1.题目解析 求和_牛客题霸_牛客网 (nowcoder.com) 这一题&#xff0c;主要描述的就是求满足和为m的子序列&#xff0c;对与子序列的问题可以使用决策树。 2.思路分析 决策树如下图所示: 递归结束条件&#xff1a; 当当前和 sum 等于目标和 m 时&#xff0c;说明找到了一个满…

软考-下午题-试题二、三

主要是最后一问的不同解答 1、父图子图平衡 1、员工关系是否存在传递依赖&#xff1f;用100字以内的文字说明理由。2019 2、在职员关系模式中&#xff0c;假设每个职员有多名家属成员&#xff0c;那么职员关系模式存在什么问题&#xff1f; 应如何解决&#xff1f;2020 职员关系…

《计算机网络微课堂》1-4 计算机网络的定义和分类

本节课我们介绍计算机网络的定义和分类。 首先来看计算机网络的定义&#xff1a;计算机网络的精确定义并未统一&#xff0c;换句话说&#xff0c;全世界没有一个对计算机网络的公认的唯一定义。 这里我们给出一个计算机网络的最简单定义&#xff0c;即计算机网络是一些互相连接…

技术前沿 |【BLIP:统一理解和生成的自举多模态模型研究】

BLIP&#xff1a;统一理解和生成的自举多模态模型研究 摘要引言一、BLIP模型概述二、 BLIP模型在多模态任务中的应用三、总结 摘要 本文介绍了BLIP&#xff08;Bootstrapping Language-Image Pre-training&#xff09;模型&#xff0c;一个前沿的多模态模型&#xff0c;通过自…

Could not create connection to database server的错误原因

1、使用MyBatis 连接数据库报错 org.apache.ibatis.exceptions.PersistenceException: ### Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not create connection to database server. ### The error may …

软件工程基础知识

一、软件工程概述 二、软件开发模型 三、软件开发方法 四、需求分析 五、系统设计 六、系统测试 七、软件开发项目管理 八、软件质量 九、软件度量