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