В вашем коде вы обрабатываете 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();
}