C# 关闭在UserControl中打开的一个或多个窗体

C# 关闭在UserControl中打开的一个或多个窗体,c#,forms,winforms,user-controls,C#,Forms,Winforms,User Controls,我有一个主窗体(Form1)和一个UserControl(ucModule2)。 ucModule2包含一个按钮(simpleButton1),用于打开另一个表单(Form2)。 在Form1上,我有一个按钮(UsrCtrlDialog),它应该关闭Form2 我有两种情况: 场景1: 我的ucModule2.cs: public partial class ucModule2 : UserControl { public static Form2 fr2 = new Form2();

我有一个主窗体(
Form1
)和一个UserControl(
ucModule2
)。
ucModule2
包含一个按钮(
simpleButton1
),用于打开另一个表单(
Form2
)。
Form1
上,我有一个按钮(
UsrCtrlDialog
),它应该关闭
Form2

我有两种情况:

场景1: 我的
ucModule2.cs

public partial class ucModule2 : UserControl
{
    public static Form2 fr2 = new Form2();
    private void simpleButton1_Click(object sender, EventArgs e)
    {
        //Form2 fr2 = new Form2();
        fr2.Show();
        fr2.TopMost = true;
        textModule2 = textBox_ucModule2.Text;
    }
 }
public partial class ucModule2 : UserControl
{
    //public static Form2 fr2 = new Form2();
    private void simpleButton1_Click(object sender, EventArgs e)
    {
        Form2 fr2 = new Form2();
        fr2.Show();
        fr2.TopMost = true;
        textModule2 = textBox_ucModule2.Text;
    }
}
Form1
用于关闭
Form2
的按钮:

private void UsrCtrlDialog_Click(object sender, EventArgs e)
{
    // Form2 fr2 = new Form2();            
    ucModule2.fr2.TopMost = false;
    ucModule2.fr2.Close();
    ucModule2.fr2.Dispose();
}
ucModule2.fr2.TopMost = false;
// (...)
在这种情况下,
Form2
只打开一次,当
Form1
中的
UsrCtrlDialog
按钮关闭时关闭。但是如果我想再次打开
Form2
,我会在
fr2.Show()上得到:

System.ObjectDisposedException
exception('无法访问已处置的 反对。”`

我知道当我想再次打开
Form2
时,不会创建
Form2
类型的新对象。
在旧的Form2关闭后,我能做些什么才能打开新的Form2

场景2: 我的
ucModule2.cs

public partial class ucModule2 : UserControl
{
    public static Form2 fr2 = new Form2();
    private void simpleButton1_Click(object sender, EventArgs e)
    {
        //Form2 fr2 = new Form2();
        fr2.Show();
        fr2.TopMost = true;
        textModule2 = textBox_ucModule2.Text;
    }
 }
public partial class ucModule2 : UserControl
{
    //public static Form2 fr2 = new Form2();
    private void simpleButton1_Click(object sender, EventArgs e)
    {
        Form2 fr2 = new Form2();
        fr2.Show();
        fr2.TopMost = true;
        textModule2 = textBox_ucModule2.Text;
    }
}
在这种情况下,只要单击
simpleButton1
,我就可以打开任意多个
Form2
窗口。例如,我按了3次
simpleButton1
。我将有3个
Form2
窗口


当我按下按钮form
UsrCtrlDialog
Form1
时,如何关闭3
Form2
窗口?如何将
fr2
对象从
ucModule2.cs
获取到
Form1.cs

在代码中,您将用户控件视为静态类对象,使用其类型访问字段和属性s:

public partial class ucModule2 : UserControl 
{ 
     public static Form2 fr2 = new Form2();
     // (...)
}
然后,在
表格1
中:

private void UsrCtrlDialog_Click(object sender, EventArgs e)
{
    // Form2 fr2 = new Form2();            
    ucModule2.fr2.TopMost = false;
    ucModule2.fr2.Close();
    ucModule2.fr2.Dispose();
}
ucModule2.fr2.TopMost = false;
// (...)
ucModule2
与UserControl类型的名称相同,因此您试图使用类型来设置属于该控件的实例的字段/属性

如果您将
ucModule2
的实例添加到表单中,则设计师会将UC的第一个实例重命名为
ucModule21

通常,将索引值(
1
,如果它是该类型的第一个实例)添加到所创建类型的名称中

您需要使用该UserControl(或任何其他控件)的实例成员,而不是其类型

关于该主题的一些文件:


类和结构具有表示其数据和结构的成员 类的成员包括在 类以及所有成员(构造函数和终结器除外) 在其继承层次结构的所有类中声明

创建只允许自身一个实例的非静态类 要创建,请参阅:

在为类型分配名称时,遵循标准命名约定也非常重要。大多数开发人员假定类型名称使用Pascal大小写约定,而此类型的实例将使用驼峰大小写约定命名,如下所示:

MyUserControl myUsrControl = new MyUserControl();
myUsrControl.Show();
您还可以在此处看到用于这两种颜色的不同标记颜色


格式1中的

Form1
(其父窗体)调用UserControl的
SetForm()
方法。
之后,
Form1
可以使用UserControl的
public FormInstance
属性

public partial class Form1: Form
{
    // If an Instance of the UC has been added in the Form's Designer,
    // use that instance reference instead 
    UCModule2 ucModule2 = new UCModule2();

    private void Form1_Load(object sender, EventArgs e)
    {
        ucModule2.Location = new Point(100, 100);
        this.Controls.Add(ucModule2);
        ucModule2.SetForm(typeof(Form2));
    }

    private void UsrCtrlDialog_Click(object sender, EventArgs e)
    {
        ucModule2?.FormInstance?.Close();
    }
}
UCModule2中的(使用适当的大小写重命名类型):

如果父窗体已关闭/释放窗体实例,请重新创建一个新实例并重置公共
FormInstance
属性。
您可以确定表单的实例是否已被销毁,测试:

FormInstance is null || FormInstance.IsDisposed

处理运行时生成的不同表单类型的集合

如果此UserControl处于活动状态时需要生成多个表单,我们可以将UC的父表单确定的表单类型的每个新实例添加到列表中。然后,当父表单决定执行此操作和/或UserControl本身被销毁时,处置列表中的每个表单实例:

父窗体可以调用
SetForm(Type formType)
public方法,设置要生成的窗体类型。然后调用
CloseAllForms()
public方法在需要时关闭所有窗体。UC在销毁其句柄时调用相同的方法,以删除现有窗体实例(如有需要)

表单只需使用另一种类型调用
SetForm()
,即可更改表单类型:

ucModule2.SetForm(typeof(Form2));
// (... and after...)
ucModule2.SetForm(typeof(Form3));
UC按钮将生成指定的新表单类型

格式1

public partial class Form1: Form
{
    // If an Instance of the UC has been added in the Form's Designer,
    // use that instance reference instead 
    UCModule2 ucModule2 = new UCModule2();

    private void Form1_Load(object sender, EventArgs e)
    {
        ucModule2.Location = new Point(100, 100);
        this.Controls.Add(ucModule2);
        ucModule2.SetForm(typeof(Form2));
    }

    private void UsrCtrlChangeType_Click(object sender, EventArgs e)
    {
        ucModule2.SetForm(typeof(Form3));
    }

    private void UsrCtrlDialog_Click(object sender, EventArgs e)
    {
        ucModule2.CloseAllForms();
    }
}
UCModule2中的

public partial class UCModule2: UserControl
{
    List<Form> formsCollection = null;

    public UCModule2()
    {
        InitializeComponent();
        formsCollection = new List<Form>();
    }

    private Type FormType { get; set; }

    // Check whether the new type is different before setting the property,
    // in case the FormType property has an explicit setter.
    public void SetForm(Type formType)
    {
        if (this.FormType != formType) {
            this.FormType = formType;
        }
    }

    public void CloseAllForms()
    {
        if (formsCollection != null && formsCollection.Count > 0) {
            for (int i = formsCollection.Count - 1; i >= 0 ; i--) {
                formsCollection[i].Dispose();
            }
        }
    }

    protected override void OnHandleDestroyed(EventArgs e)
    {
        CloseAllForms();
        base.OnHandleDestroyed(e);
    }

    private void btnShowForm_Click(object sender, EventArgs e)
    {
        if (FormType == null) return;
        var instance = (Form)Activator.CreateInstance(FormType);
        formsCollection.Add(instance);
        instance.Show();
    }
public分部类UCModule2:UserControl
{
List formsCollection=null;
公共UCModule2()
{
初始化组件();
formsCollection=新列表();
}
私有类型FormType{get;set;}
//在设置属性之前,请检查新类型是否不同,
//如果FormType属性具有显式setter。
公共void SetForm(类型formType)
{
if(this.FormType!=FormType){
this.FormType=FormType;
}
}
public void CloseAllForms()
{
如果(formsCollection!=null&&formsCollection.Count>0){
对于(int i=formscolection.Count-1;i>=0;i--){
formsCollection[i].Dispose();
}
}
}
受保护的覆盖无效OnHandleDestroyed(事件参数e)
{
CloseAllForms();
碱基。经处理的雌雄同体(e);
}
私有void btnShowForm_单击(对象发送者,事件参数e)
{
if(FormType==null)返回;
var instance=(Form)Activator.CreateInstance(FormType);
formsCollection.Add(实例);
Show();
}

如果我将ucModule2.FormInstance.Close()放入UsrCtrlDialog\u单击,我会得到这个er