罗海伟 发表于 2023-12-28 15:06:26

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

在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类

public class CustomDialog : Form{

}创建CustomDialog成员变量


[*]这里使用到了两个类, Panel和ControlContainer。其中Panel充当CustomDialog的容器。ControlContainer则是Panel的容器。
public class CustomDialog : Form{
    private Panel? _panelContainer;
    private ControlContainer? _parentContainer;
    private Form? _parentForm;
    // 声明Panel,ControlContainer和Form
}定义一个ShowDialog方法

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

这部分代码最主要实现了CustomDialog在它的父控件Form中显示的功能,PS:有点简单粗暴,但是有效(_)
public class CustomDialog : Form{
    private void AddDialogToTheView(){
      if(ContainerControl is null){
            throw new NullReferenceException(nameof(_parentContainer));
      }
      //panel的高度
      int panelHeight = 350;
      int panelWidth = 500;
      
      //panel显示的位置
      int startUpLocationX = (_parentContainer.ClientSize.Width - panelWidth) / 2;
      int startUpLocationY = (_parentContainer.ClientSize.Height - panelHeight) / 2;
      
      // 设置_panelContainer的属性
      _panelContainer = new Panel(){
            Height = panelHeight,
            Width = panelWidth,
            Location = new Point(startUpLocationX, startUpLocationY),
      };

      // 设置Dialog的属性
      TopLevel = false;
      DockStyle = DockStyle.Fill;
      //添加进Panel里面
      _panelContainer.Controls.Add(this);
      Contianer.Controls.Add(_panelContainer);
      // 显示Dialog
      Show();
      PanelControl.BringToFront();
      
    }

}实现伪阻塞

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

[*]如何阻塞一段代码?
我最初的做法是这样的:
public void WaitForExit(Cancellationtoken token){
    while(!toke.IsCancellationRequested){
      Application.DoEvents();
    }
}
CancellationTokenSource source = new CancellationTokenSource();
WaitForExit(source.Token);

//user cancel
source.Cancel();
这个写法有效,但还是不够优雅
来源:https://www.cnblogs.com/echo-sama/archive/2023/12/28/17932701.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: [Winform]在Form里显示模态对话框ModalDialog