Предположим, у вас есть форма FormBase
а все остальные формы наследуются от этой формы.
Например, у меня есть public class Form formTest: FormBase
Что у меня сейчас в ctor от formTest:
public class Form formTest : FormBase
{
public formTest()
{
InitializeComponent();
Program.MainForm.AddToFormSizes(this, this.Size);
}
}
Этот код добавляет экземпляр formTest
в словарь на главной форме с его size
Это работает, но я хотел бы переместить этот код в FormBase
поэтому мне не нужно помещать эту строку кода в каждую унаследованную форму.
public class Form FormBase : Form
{
public FormBase()
{
InitializeComponent();
Program.MainForm.AddToFormSizes(this, this.Size);
}
}
Теперь проблема в том, что когда я это сделаю, size
будет иметь размер FormBase
во время разработки, а не размер formTest
.
Есть ли способ в FormBase
захватить размер formTest
или любой другой формы, унаследованной от FormBase
?
для справки, это код AddToFormSizes
в MainForm
private Dictionary<Form, Size> _formSizes = new Dictionary<Form, Size>();
public void AddToFormSizes(Form form, Size size)
{
_formSizes.Add(form, form.Size);
}
Проблема:
Используя Form
качестве базы для других форм, в конструкторе базового класса ссылка this
возвращает Size
базового класса вместо Size
производного класса.
public class FormBase : Form
{
public FormBase()
{
InitializeComponent();
Program.MainForm.AddToFormSizes(this, this.Size);
}
}
Это просто следование последовательности событий:
FormDerived derived = new FormDerived()
=> FormBase.InitializeComponent()
=> FormDerived.InitializeComponent()
derived.Show()
=> FormBase.OnHandleCreated()
Учитывая конструктор формы, производной от FormBase
:
public class FormDerived : FormBase
{
public FormDerived() => InitializeComponents();
}
когда класс создается впервые:
FormDerived derived = new FormDerived();
derived.Show();
конструктор базового класса (FormBase
) вызывается первым.
На этом этапе ссылка this
установлена на FormDerived
, но все свойства, включая Name
и FormDerived
формы (Text
), установлены на значения базового класса.
Следовательно, вызывая метод, который использует this
в конструкторе базового класса:
Program.MainForm.AddToFormSizes(this, this.Size);
this.Size
вернет размер базового класса, а не производного класса.
Конструктор FormDerived
вызывается следующим. На этом этапе будут установлены все свойства, определенные в методе InitializeComponent()
.
Если метод AddToFormSizes()
перемещен в конструктор производного класса, this
будет ссылаться на ожидаемые значения. Но вызов статического метода должен быть вставлен в каждый производный класс FormBase
.
AddToFormSizes()
можно переместить и OnHandleCreated()
из переопределенного OnHandleCreated()
базового класса, который будет вызываться при первом показе производной формы:
derived.Show();
вызовет вызов FormBase.OnHandleCreated()
.
На этом этапе ссылка this
уже установлена на производный класс, и все свойства, определенные в InitializeComponent()
, уже будут установлены на значения производного класса. Name
, Text
и Size
включены, конечно.
Здесь this
FormDerived
со всеми свойствами, установленными в его конструкторе:
public class FormBase : Form
{
public FormBase() => InitializeComponent();
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
Program.MainForm.AddToFormSizes(this, this.Size);
}
}
formTest
устанавливается (изменяется) вformTest.InitializeComponent()
которомFormBase
ничего не знает. Прежде чем это произойдет,formTest.Size
- это размер, полученный изFormBase
.Program.MainForm.AddToFormSizes(this, this.Size);
дляprotected override void OnHandleCreated(EventArgs e)
, послеbase.OnHandleCreated(e);
, Внутри вашейbase
формы.