翼度科技»论坛 编程开发 .net 查看内容

[Winform]在Form里显示模态对话框ModalDialog

7

主题

7

帖子

21

积分

新手上路

Rank: 1

积分
21
在Form里显示模态Dialog

问题

如何在WinForm的一个Form里面弹出一个模态Dialog?
背景

程序的框架是Winform,只有一个窗口MainForm。MainForm里面是一个TabControl,每个TabPage是一个Form,每个TabPage的Form相互独立,互不干扰,TabPage间可以随时切换。由于有某些需求,TabPage需要接受用户输入,并等待输入完成,才能执行后面的代码,此时,程序是需要阻塞等待输入的,所以需要弹出一个模态Dialog。

  • 为什么不用MessageBox呢?因为MessageBox是直接弹出一个模态对话框且该对话框是一个新的窗口,这时候整个MainForm是伪阻塞状态,用户无法通过与MainForm的其他区域交互,包括点击标签页切换到其他TabPage。所以,我需要该对画框只在Form里显示。
  • 为什么不用MDI呢? 最主要的原因是TabControl里的Form,其TopLevel属性是false的,如果想在Form里面添加MDI窗口,需要将Form的TopLevel属性设置为true,这时我将无法使用TabControl。
代码实现

创建一个CustomDialog类,继承Form类
  1. public class CustomDialog : Form{
  2. }
复制代码
创建CustomDialog成员变量


  • 这里使用到了两个类, Panel和ControlContainer。其中Panel充当CustomDialog的容器。ControlContainer则是Panel的容器。
  1. public class CustomDialog : Form{
  2.     private Panel? _panelContainer;
  3.     private ControlContainer? _parentContainer;
  4.     private Form? _parentForm;
  5.     // 声明Panel,ControlContainer和Form
  6. }
复制代码
定义一个ShowDialog方法

要显示模态Dialog,当然要是实现ShowDialog方法啦!这里定义了一个ShowDialog方法,和其他ShowDialog方法有些许不同,该方法的参数是ControlContainer类型, 用于接收一个控件作为父控件
  1. public class CustomDialog : Form{
  2.     public void ShowDialog(ControlContainer parentControl){
  3.         //TODO
  4.     }
复制代码
设置CustomDialog.PaneContainer的属性和内容

这部分代码最主要实现了CustomDialog在它的父控件Form中显示的功能,PS:有点简单粗暴,但是有效(_)
  1. public class CustomDialog : Form{
  2.     private void AddDialogToTheView(){
  3.         if(ContainerControl is null){
  4.             throw new NullReferenceException(nameof(_parentContainer));
  5.         }
  6.         //panel的高度
  7.         int panelHeight = 350;
  8.         int panelWidth = 500;
  9.         
  10.         //panel显示的位置
  11.         int startUpLocationX = (_parentContainer.ClientSize.Width - panelWidth) / 2;
  12.         int startUpLocationY = (_parentContainer.ClientSize.Height - panelHeight) / 2;
  13.         
  14.         // 设置_panelContainer的属性
  15.         _panelContainer = new Panel(){
  16.             Height = panelHeight,
  17.             Width = panelWidth,
  18.             Location = new Point(startUpLocationX, startUpLocationY),
  19.         };
  20.         // 设置Dialog的属性
  21.         TopLevel = false;
  22.         DockStyle = DockStyle.Fill;
  23.         //添加进Panel里面
  24.         _panelContainer.Controls.Add(this);
  25.         Contianer.Controls.Add(_panelContainer);
  26.         // 显示Dialog
  27.         Show();
  28.         PanelControl.BringToFront();
  29.         
  30.     }
  31. }
复制代码
实现伪阻塞

要说实现这个CustomDialog哪里最难,应该是这个伪阻塞功能最难。前面的View相关的方案,一般人稍微思考一下都可以想出来。但是想优雅的实现CustomDialog的伪阻塞功能,确实不易

  • 如何阻塞一段代码?
    我最初的做法是这样的:
  1. public void WaitForExit(Cancellationtoken token){
  2.     while(!toke.IsCancellationRequested){
  3.         Application.DoEvents();
  4.     }
  5. }
  6. CancellationTokenSource source = new CancellationTokenSource();
  7. WaitForExit(source.Token);
  8. //user cancel
  9. source.Cancel();
复制代码
这个写法有效,但还是不够优雅
来源:https://www.cnblogs.com/echo-sama/archive/2023/12/28/17932701.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具