【发布时间】:2010-11-27 01:52:48
【问题描述】:
如何避免在c#中出现多个windows窗体实例??我只想运行一个表单实例。因为有机会从我的应用程序的许多页面中打开相同的表单。
【问题讨论】:
如何避免在c#中出现多个windows窗体实例??我只想运行一个表单实例。因为有机会从我的应用程序的许多页面中打开相同的表单。
【问题讨论】:
一个例子:CodeProject: Simple Singleton Forms(好吧,它在 VB.NET 中,但只是给你一个线索)
【讨论】:
您可以在打开表单之前检查现有流程:
using System.Diagnostics;
bool ApplicationAlreadyStarted()
{
return Process.GetProcessesByName(Process.GetCurrentProcess.ProcessName).Length == 0;
}
不知道 GetProcessesByName 方法是否受到 UAC 或其他安全措施的影响。
【讨论】:
是的,它有单例模式,
创建单例对象的代码,
public partial class Form2 : Form
{
.....
private static Form2 inst;
public static Form2 GetForm
{
get
{
if (inst == null || inst.IsDisposed)
inst = new Form2();
return inst;
}
}
....
}
调用/显示此表单,
Form2.GetForm.Show();
【讨论】:
单例不是面向对象的。它们只是全局变量的对象版本。您可以做的是将 Form 类的构造函数设为私有,这样任何人都不会意外创建其中之一。然后在反射中调用,将 ctor 转换为 public 并确保创建一个且只有一个实例。
【讨论】:
如果您的系统有可能为不同的实例数据显示相同类型的表单,那么您可以创建一个检查系统来迭代所有现有的打开表单,寻找唯一的实例数据标识符,然后重新显示任何找到的表单。
例如具有包含公共属性“CustomerUniqueID”的表单类“CustomerDetails”:
foreach(Form f in CurrentlyDisplayedForms)
{
CustomerDetails details = f as CustomerDetails;
if((details != null) && (details.CustomerUniqueUD == myCustomerID))
{
details.BringToFront();
}
else
{
CustomerDetails newDetail = new CustomerDetails(myCustomerID);
}
}
我们还使用相同的机制来自动强制刷新已编辑和保存客户数据的数据绑定。
【讨论】:
试试这个代码
Public class MyClass
{
//Create a variable named
public static int count = 0;
//Then increment count variable in constructor
MyClass()
{
count++;
}
}
在为上述类“MyClass”创建对象时,检查计数值是否大于 1
class AnotherClass
{
public void Event()
{
if(ClassName.Count <= 1)
{
ClassName classname=new ClassName();
}
}
}
【讨论】:
这是我在 ShowForm() 中的解决方案:
private void ShowForm(Type typeofForm, string sCaption)
{
Form fOpen = GetOpenForm(typeofForm);
Form fNew = fOpen;
if (fNew == null)
fNew = (Form)CreateNewInstanceOfType(typeofForm);
else
if (fNew.IsDisposed)
fNew = (Form)CreateNewInstanceOfType(typeofForm);
if (fOpen == null)
{
fNew.Text = sCaption;
fNew.ControlBox = true;
fNew.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
fNew.MaximizeBox = false;
fNew.MinimizeBox = false;
// for MdiParent
//if (f1.MdiParent == null)
// f1.MdiParent = CProject.mFMain;
fNew.StartPosition = FormStartPosition.Manual;
fNew.Left = 0;
fNew.Top = 0;
ShowMsg("Ready");
}
fNew.Show();
fNew.Focus();
}
private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
{
ShowForm(typeof(FAboutBox), "About");
}
private Form GetOpenForm(Type typeofForm)
{
FormCollection fc = Application.OpenForms;
foreach (Form f1 in fc)
if (f1.GetType() == typeofForm)
return f1;
return null;
}
private object CreateNewInstanceOfType(Type typeofAny)
{
return Activator.CreateInstance(typeofAny);
}
public void ShowMsg(string sMsg)
{
lblStatus.Text = sMsg;
if (lblStatus.ForeColor != SystemColors.ControlText)
lblStatus.ForeColor = SystemColors.ControlText;
}
【讨论】:
当您显示对话框时,只需使用.ShowDialog(); 而不是.Show();
【讨论】:
为了让这个表单再次出现在前台,我应用到我的项目中的一个解决方案是:
private bool checkWindowOpen(string windowName)
{
for (int i = 0; i < Application.OpenForms.Count; i++)
{
if (Application.OpenForms[i].Name.Equals(windowName))
{
Application.OpenForms[i].BringToFront();
return false;
}
}
return true;
}
windowName 本质上是您的 Windows 窗体的类名,并且 返回值可用于不创建新的表单实例。
【讨论】:
检查这个link:
using System;
public sealed class Singleton
{
private static volatile Singleton instance;
private static object syncRoot = new Object();
private Singleton() {}
public static Singleton Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new Singleton();
}
}
return instance;
}
}
}
【讨论】:
这是一个简单的方法。
检查表单是否为空,或已被处置。如果是这样,我们将创建一个新的表单实例。
否则我们只显示已经运行的表单。
Form form;
private void btnDesktop_Click(object sender, EventArgs e)
{
if (form == null || desktop.IsDisposed)
{
form = new Form();
form.Show();
}
else
{
form.WindowState = FormWindowState.Normal;
}
}
【讨论】:
private static MyForm _myForm;
internal static MyForm form
{
get
{
if (_myForm == null)
{
_myForm = new MyForm();
}
return _myForm;
}
}
public MyForm()
{
InitializeComponent();
_myForm = this;
}
private void MyForm_FormClosed(object sender, FormClosedEventArgs e)
{
_myForm = null;
}
【讨论】: