Как получить размер унаследованной формы в базовой форме? - PullRequest
2 голосов
/ 19 апреля 2019

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

1 Ответ

2 голосов
/ 19 апреля 2019

Проблема :
Использование 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()

Учитывая конструктор Form, полученный из 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);
    }
}
...