Закрыть форму или несколько форм, открытых в UserControl - PullRequest
1 голос
/ 28 января 2020

У меня есть основная форма (Form1) с UserControl (ucModule2).
ucModule2 содержит кнопку (simpleButton1), которая открывает другую форму (Form2).
Вкл. Form1, у меня есть кнопка (UsrCtrlDialog), которая должна закрыться Form2.

У меня есть два сценария ios:

Сценарий 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;
    }
 }

Form1 используется кнопка закрыть Form2:

private void UsrCtrlDialog_Click(object sender, EventArgs e)
{
    // Form2 fr2 = new Form2();            
    ucModule2.fr2.TopMost = false;
    ucModule2.fr2.Close();
    ucModule2.fr2.Dispose();
}

В этом случае Form2 открывается только один раз и закрывается, когда кнопка UsrCtrlDialog из Form1 закрыта. Но если я хочу открыть снова Form2, я получаю, fr2.Show():

System.ObjectDisposedException исключение ('Не удается получить доступ к удаленному объекту.' '

Я знаю, что когда я хочу снова открыть 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;
    }
}

В этом сценарии я могу открыть столько Form2 windows, сколько нажму simpleButton1 Например, я нажимаю 3 раза simpleButton1. У меня будет 3 Form2 windows.

Как можно закрыть 3 Form2 windows, когда я нажимаю UsrCtrlDialog кнопку формы Form1? Как я могу получить объект fr2 от ucModule2.cs до Form1.cs?

1 Ответ

1 голос
/ 28 января 2020

В вашем коде вы обрабатываете UserControl как объект класса stati c, используя его тип для доступа к полям и свойствам:

public partial class ucModule2 : UserControl 
{ 
     public static Form2 fr2 = new Form2();
     // (...)
}

Затем в Form1:

ucModule2.fr2.TopMost = false;
// (...)

ucModule2 - это то же имя типа UserControl, поэтому вы пытаетесь использовать Type для установки полей / свойств, принадлежащих Экземпляр этого Контроля.

Если вы добавили в форму инстанс ucModule2, то конструктор переименовал бы первый инстанс U C в ucModule21.
Как обычно, добавив значение индекса ( 1, если это первый экземпляр этого Типа) с именем созданного Типа.

Вам необходимо использовать элемент Instance этого UserControl (или любого другого элемента управления), а не его тип.

Некоторая документация по теме:

Наследование (C# Руководство по программированию)
Элементы (C# Руководство по программированию)

У классов и структур есть члены, которые представляют их данные и поведение. Членами класса являются все члены, объявленные в классе, а также все члены (кроме конструкторов и финализаторов), объявленные во всех классах в его иерархии наследования ...

Stati c Классы и Stati c Члены класса

Чтобы создать класс non-stati c, который позволяет создавать только один его экземпляр, см .:
Реализация Singleton в C#.

Также очень важно следовать стандартному соглашению об именах при назначении имен для типов. Большинство разработчиков предполагают, что имя типа использует соглашение Pascal Case, в то время как экземпляр этого типа будет называться с использованием соглашения Camel Case, как в:

MyUserControl myUsrControl = new MyUserControl();
myUsrControl.Show();

Вы также можете увидеть различные Цвета разметки, используемые для двух, здесь


В Form1 :

Вызвать метод UserControl SetForm() из Form1 (его родительская форма ).
После этого 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 (тип переименован с использованием правильного регистра):

Если экземпляр формы был закрыт / удален родительской формой, заново создайте новый экземпляр и сбросить свойство c FormInstance.
Вы можете определить, был ли уничтожен экземпляр формы, протестировав:

FormInstance is null || FormInstance.IsDisposed

public partial class UCModule2: UserControl
{
    public Form FormInstance { get; private set; }

    public Form SetForm(Type formType)
    {
        if (this.FormInstance == null || this.FormInstance.IsDisposed) {
            this.FormInstance = (Form)Activator.CreateInstance(formType);
        }
        return this.FormInstance;
    }

    private void simpleButton1_Click(object sender, EventArgs e)
    {
        if (this.FormInstance is null || this.FormInstance.IsDisposed) {
            this.SetForm(FormInstance.GetType());
        }
        this.FormInstance?.Show();
    }
}

Обрабатывать коллекцию различных типов форм, сгенерированных во время выполнения

Если необходимо создать более одной формы, когда этот UserControl активен, мы можем добавить каждый новый экземпляр типа формы, определяемый Родительская форма U C, в Список. Затем удалите каждый экземпляр формы в списке, когда родительская форма решит сделать это и / или когда сам UserControl будет уничтожен:

родительская форма может вызвать SetForm(Type formType) publi c метод, устанавливающий тип Формы для генерации. Затем вызовите метод CloseAllForms() publi c, чтобы закрыть их все при необходимости. U C вызывает тот же метод, когда его дескриптор уничтожается, чтобы удалить существующие экземпляры Form (если требуется).

Форма изменяет тип формы, просто вызывая SetForm() с другим типом:

ucModule2.SetForm(typeof(Form2));
// (... and after...)
ucModule2.SetForm(typeof(Form3));

Кнопка U C сгенерирует новый указанный тип формы.

In Form1:

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();
    }
}

In 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();
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...