如何制作单个实例表单(不是应用程序)?

在我的C#应用​​程序中,我有一个可以从菜单命令打开的选项对话框。

我想确保选项对话框只有一个实例(用户不能在给定时间打开多个选项窗口)而不使其成为模态。

此外,如果用户已打开此窗口,并且他单击菜单项以再次打开它,则应用程序只会使已经可见的表单成为最顶层的窗口。

谁能指出我如何完成这些任务的方向?

非常感谢你。

您需要此表格作为财产

Form1 myForm = null; private void Form1_FormClosed(object sender, FormClosedEventArgs e) { myForm = null; } private void ShowForm() { if (myForm != null) { myForm.BringToFront(); } else { myForm = new Form1; myForm.Show(); } } 

嗯,最简单的方法是使用一个静态字段来存储对单个实例的引用或null,然后是一个检索它或创建一个新方法的方法。

请注意,这与将其设为单例不同 – 因为我假设表单已关闭,您希望下次创建新实例。 (替代方案 – 隐藏它并重复使用 – 在STO的答案中显示。)你可能想要这样的东西:

 public class OptionsDialog : Form { private static OptionsDialog openForm = null; // No need for locking - you'll be doing all this on the UI thread... public static OptionsDialog GetInstance() { if (openForm == null) { openForm = new OptionsDialog(); openForm.FormClosed += delegate { openForm = null; }; } return openForm; } } 

当然,您可能希望使该方法执行“将其置于最前面”的步骤。

您需要阻止表单关闭。 如果不这样,表格将被处理并变得无法使用。 您可以通过实现FormClosing事件来完成此操作:

  protected override void OnFormClosing(FormClosingEventArgs e) { if (e.CloseReason == CloseReason.UserClosing) { this.Hide(); e.Cancel = true; } } 

要使它成为单例,只需跟踪主表单类中表单的生命周期:

  frmOptions options; private void btnShowOptions_Click(object sender, EventArgs e) { if (options == null) { options = new frmOptions(); // To make absolutely sure: options.FormClosed += (o, ea) => options = null; } else { options.WindowState = FormWindowState.Normal; } options.Show(); } 

你可以使用这样的代码:

 private MyDialogForm _FormInstance; public void ShowOptions() { if (_FormInstance == null) { _FormInstance = new MyDialogForm(); _FormInstance.FormClosing += (s,e) => { e.Cancel = true; _FormInstance.Hide(); } } _FormInstance.Show(); } 

我假设你至少有两种forms。 一种forms,称为frmMain,允许您打开frmOptions。 在frmMain中,添加一个frmOptions类型的变量,如下所示:

 public partial class frmMain : Form { private frmOptions optionsInstance = null; ... 

在打开“选项”对话框的例程中,添加以下内容:

 if (optionsInstance == null || !optionsInstance.Visible) { optionsInstance = new frmOptions(); optionsInstance.Show(); } 

当frmOptions关闭时,optionsInstance将不为null,这就是为什么在实例化frmOptions实例之前检查它是否可见。

如果这对您不起作用,您可以尝试使用互斥锁,但这可能有点过分。

根据Jon Skeet的回答 ,我使用以下代码将表单显示为模式对话框。

  if (this.aboutForm == null) { this.aboutForm = new AboutForm(); this.aboutForm.FormClosed += (sender2, e2) => { this.aboutForm = null; }; this.aboutForm.ShowDialog(this); } else { this.aboutForm.Focus(); } 

我必须这样做,因为我有一个菜单项,在主窗体的菜单中显示关于窗体,并在通知图标的上下文菜单中。 如果我使用主窗体的菜单打开“关于”窗体,我仍然可以使用通知图标的上下文菜单项打开另一个实例。

  Main_Frm _main_Frm = null; private void Show_bt_Click(object sender, EventArgs e) { if (_main_Frm != null) { _main_Frm .BringToFront(); } else { _main_Frm = new Comission_Frm(); _main_Frm .Show(); } //This condition used when you closed the form the form will disposed and when you reopen. if (_main_Frm .IsDisposed) { _main_Frm = new _Main_Frm (); _main_Frm .Show(); } }