Страницы

Поиск по вопросам

четверг, 9 апреля 2020 г.

Почему родитель формы равен Null?

#c_sharp #winforms #null

                    
Выдержка кода из главной формы:

public partial class Main : Form
{
    public NetComm.Host server;
    public NetComm.Client client;
    public Main()
    {
        InitializeComponent();
    }
    private void ToolStripMIConnect_Click(object sender, EventArgs e)
    {
        ClientPref formConnect = new ClientPref();
        formConnect.Owner = this;
        formConnect.ShowDialog();
    }
}


Выдержка кода из создаваемой формы:

public partial class ClientPref : Form
{
    Main formMain;
    public ClientPref()
    {
        InitializeComponent();
        formMain = this.Owner as Main;
    }
    private void btnConnect_Click(object sender, EventArgs e)
    {
        if (formMain != null) //следующий бок не выполняется т.к. formMain равен null
        {
            if (IsAddressValid(this.txtBoxIP.Text))
            {
            formMain.ClientStart(Convert.ToInt32(this.txtBoxPort.Text), this.txtBoxIP.Text,
"Соперник");
            }
            else toolTipClient.Show("Введен некорректный IP-адрес.", this.txtBoxIP);
        }

    }


Почему formMain равен null или как в итоге обратиться к методу ClientStart формы Main?
    


Ответы

Ответ 1



Простой вариант - переписать вот так, сделать поле вычислимым свойством: Main FormMain { get { return this.Owner as Main } }; Тогда в btnConnect_Click всё должно работать.

Ответ 2



Когда выполняется код formMain = this.Owner as Main; owner еще не установлен, так как он устанавливается после выполнения конструктора, поэтому formMain всегда null Решить можно передавая параметр в конструктор, для этого надо добавить конструктор с параметром public ClientPref(Main owner):this() { formMain = this.Owner as Main; } и вызывать уже его private void ToolStripMIConnect_Click(object sender, EventArgs e) { ClientPref formConnect = new ClientPref(this); formConnect.ShowDialog(); }

Ответ 3



Если ClientPref - это диалог, то его надо сделать независимым и он не должен управлять формой, т.е. в диалоге не должно быть вызова formMain.ClientStart(...), т.к. это нарушает один из основных принципов дизайна в ООП - принцип единственной обязанности (англ. Single responsibility principle - SRP). Диалог должен получить данные от пользователя, проверить их и предоставить доступ к этим данных. Больше никакой обязанности у диалога быть не должно. Посмотрите, например, на OpenFileDialog, в нем нет ссылки на главную форму. Чтобы диалог ClientPref сделать независимым, надо значения, выбранные пользователем, сохранять в свойствах диалога. public partial class ClientPref : Form { public int Port { get; private set; } public string IP { get; private set; } void Validate() { if (IsAddressValid(this.txtBoxIP.Text)) { this.Post = Convert.ToInt32(this.txtBoxPort.Text); this.IP = this.txtBoxIP.Text; } } } В диалоге надо перехватывать нажатие Esc -- работающий пример диалога тут. Для вызова диалога и получения данных из него, в главной форме пишем: var fc = new ClientPref(); if(fc.ShowDialog() == DialogResult.OK) ClientStart(fc.Port, fc.IP); т.е. форма решает когда вызвать диалог и что делать с данными введенными пользователем. Если по какой-то причине надо получить ссылки на все открытые формы, то это можно сделать так: using System.Windows.Forms; var forms = Application.OpenForms; Открытую форму определенного типа можно получить так using System.Linq; var main = Application.OpenForms.OfType
().First(); Если есть несколько форм одинакового типа, то их можно отпичать по значению свойства Name, но таких ситуаций лучше избегать. Почему нежелательно передавать ссылки? Представьте, что в приложении десяток форм. В каждую форму передается ссылка на главную форму, а также возможно, что передается ссылка на какую-то дополнительную форму. Если в дальнейшем надо будет изменить логику взаимодействия форм, то возникнут сложности с рефакторингом. Поэтому надо стараться уменьшать связанность кода, и если есть возможность передать ссылку через Application.OpenForms, то лучше так и делать.

Комментариев нет:

Отправить комментарий