自定义询问窗口
当需要关闭系统或进行删除数据或进行其他操作的时候,需要询问用户是否要执行对应的操作。那么就需要一个弹窗来给用户进行提示。
一.添加自定义询问窗口视图 (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;};}}
}