#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, то лучше так и делать.
Комментариев нет:
Отправить комментарий