自定義詢問窗口
當需要關閉系統或進行刪除數據或進行其他操作的時候,需要詢問用戶是否要執行對應的操作。那么就需要一個彈窗來給用戶進行提示。
一.添加自定義詢問窗口視圖 (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;};}}
}