Как получить размер унаследованной формы в базовой форме?

Предположим, у вас есть форма с именем 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);
}

person GuidoG    schedule 19.04.2019    source источник
comment
Я не думаю, что ты можешь что-то сделать. Размер formTest установлен (изменен) в formTest.InitializeComponent(), о котором FormBase ничего не знает. До того, как это произойдет, formTest.Size - это размер, производный от FormBase.   -  person 41686d6564    schedule 19.04.2019
comment
Переместите эту штуку (компилируется?): Program.MainForm.AddToFormSizes(this, this.Size); в protected override void OnHandleCreated(EventArgs e) после base.OnHandleCreated(e);. Внутри вашей base формы.   -  person Jimi    schedule 19.04.2019
comment
@Jimi Хорошая идея! Кажется, это действительно работает. Я исправился.   -  person 41686d6564    schedule 19.04.2019
comment
@Jimi Да, это компилируется. MainForm - это просто статическая ссылка в Program.cs для доступа к моей основной форме. Я попробую это предложение, спасибо   -  person GuidoG    schedule 19.04.2019
comment
Кстати, вам не нужна статическая ссылка MainForm в Program.cs. Вам просто нужно сделать AddToFormSizes() статичным. Вы можете вызвать его из членов экземпляра внутри MainForm.   -  person Jimi    schedule 19.04.2019
comment
@Jimi Мне нужна эта ссылка для других вещей, а не только для этого метода   -  person GuidoG    schedule 19.04.2019
comment
@Jimi Ваш подход работает, если вы напишете в качестве ответа, я приму его   -  person GuidoG    schedule 19.04.2019


Ответы (1)


Проблема:
При использовании Form в качестве основы для других форм в конструкторе базового класса ссылка this возвращает Size базового class вместо 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 и заголовок формы (Text) устанавливаются на значения базового класса.
Следовательно, вызов метода, который использует this в конструкторе базового класса:

Program.MainForm.AddToFormSizes(this, this.Size);

this.Size вернет размер базового класса, а не производного класса.

Следующим вызывается конструктор FormDerived. На этом этапе будут установлены все свойства, определенные в методе InitializeComponent().

Если метод AddToFormSizes() перемещен в конструктор производного класса, this будет ссылаться на ожидаемые значения. Но вызов статического метода должен быть вставлен в каждый производный класс FormBase.

Вместо этого метод AddToFormSizes() можно переместить и вызвать из переопределенного метода 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);
    }
}
person Jimi    schedule 19.04.2019