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

Ну, вот в чем дело, у меня есть MainForm, который вызывает OrderForm.Show () Теперь я хочу вызвать публичную функцию в MainForm с помощью кнопки, но я не могу.

Вот код в MainForm:

public partial class frmMain : Form
{
    public frmMain()
    {
        InitializeComponent();
    }

    // Main form
    private void MainFrm_Load(object sender, EventArgs e)
    {
        FormOrder frmO = new FormOrder();

        frmO.Show();
    }

    public void Refresh() 
    {
        // some action
    }
 }

И в OrderForm я делаю это:

public partial class FormOrder : Form
{
    public FormOrder()
    {
        InitializeComponent();
    }

    private void ShowForm()
    {
        // some action
    }

    private void btnCopy_Click(object sender, EventArgs e)
    {
        Form  form = Form.ActiveForm as frmMain;

        if (form != null)
        {
            form.Refresh();
        }

    }
}

поэтому в программе я запускаю MainForm.Show (), затем загружаю OrderForm. Затем, когда я нажимаю кнопку «Копировать», в MainForm запускается публичная функция «Обновить». Но я не могу заставить его работать, он всегда возвращает ноль в:

  Form  form = Form.ActiveForm as frmMain;

так как же я могу получить активную форму, это другое решение? или я ошибаюсь ?? Заранее спасибо за ответ:)

Ответы [ 4 ]

4 голосов
/ 19 октября 2011

Вы получаете нулевое значение, потому что ваша активная форма - та, в которой вы находитесь, и она не относится к типу frmMain. (Я думаю, что вы действительно путаете активную форму с родительской формой?)

Могут быть способы сделать это. Вы можете сделать свой frmMain синглтоном, но это странно и некрасиво и не рекомендуется в последнее время, или вы можете передать ссылку на него своим детям. Вот один простой способ:

public partial class frmMain : Form
{
    public frmMain()
    {
        InitializeComponent();
    }

    // Main form
    private void MainFrm_Load(object sender, EventArgs e)
    {
        FormOrder frmO = new FormOrder(this); // pass a ref of self

        frmO.Show();
    }

    public void Refresh() 
    {
        // some action
    }
 }

И в OrderForm:

public partial class FormOrder : Form
{
    private frmMain _parent; // create a field that refers to the parent
    public FormOrder(frmMain parent) // mod the constructor
    {
        if (parent == null) throw new NullReferenceException("Can't be NULL!!!"); // check clause

        _parent = parent; // assign the ref of the parent

        InitializeComponent();
    }

    private void ShowForm()
    {
        // some action
    }

    private void btnCopy_Click(object sender, EventArgs e)
    {
            _parent.Refresh(); // make the call to parent
    }
}

Вы могли бы сделать это лучше, используя интерфейс, но общая идея была бы такой же.

1 голос
/ 19 октября 2011

Хотя остальные ответы абсолютно верны, я хотел бы предложить гораздо более простой, но "грязный" способ сделать это.

Каждый компонент имеет свойство Tag, в котором можно хранить любое пользовательское значение или ссылку. Идея состоит в том, чтобы сохранить ссылку на основную форму во второй форме Tag и получить к ней доступ из обработчик события нажатия кнопки.

Хорошо в том, что вам не нужно писать много кода или создавать какую-либо структуру данных.

Грязная вещь в том, что ни инфраструктура во время выполнения, ни компилятор во время компиляции не имеют никакого представления о том, что вы храните в .Tag, и, поскольку она не введена правильно, вы делаете тип приведения, в зависимости от того, сохраняете ли вы правильное значение там заранее. Если вы храните неправильное значение там, вам может быть трудно отладить причину, так как симптом не сигнализирует, где вы указали неправильное значение в Tag. Столь дикое Tag использование в команде программистов - это хорошо, если вы хотите породить много неожиданных ошибок, которые трудно обнаружить и исправить:)

Кроме того, существует только один Tag на компонент. Если вам нужно более одного пользовательского значения, вы можете в конечном итоге создать пользовательскую структуру данных, на которую Tag будет содержать ссылку, но это, вероятно, более сложный вопрос, чем все другие предложения.

public partial class frmMain : Form
{
    public frmMain()
    {
        InitializeComponent();
    }

    // Main form
    private void MainFrm_Load(object sender, EventArgs e)
    {
        FormOrder frmO = new FormOrder();

        frmO.Tag=this;
        frmO.Show();
    }

    public void Refresh() 
    {
        // some action
    }
 }


public partial class FormOrder : Form
{
    public FormOrder()
    {
        InitializeComponent();
    }

    private void ShowForm()
    {
        // some action
    }

    private void btnCopy_Click(object sender, EventArgs e)
    {
        Form  form = Tag as frmMain; // form now references the main form

        if (form != null)
        {
            form.Refresh();
        }

    }
}

Хороший пример для быстрого и грязного решения, с такими неотъемлемыми ограничениями, что вы обычно идентифицируете их только тогда, когда слишком поздно - вот почему я говорю в первую очередь;)

1 голос
/ 19 октября 2011

У вас должна быть ссылка на событие нажатия кнопки mainForm и / или mainForm, которое находится за пределами mainForm.Вы можете сделать это различными способами.Создайте статический класс, имеющий ссылку на mainForm, создайте статический класс, имеющий делегат для события click mainForm, передайте mainForm в конструктор для childForm, передайте событие делегата для mainForms click конструктору для childForm.Создайте статический метод, который обрабатывает событие click, а затем используйте его из childForm.

На самом деле все зависит от того, что вы хотите сделать, что вам нужно сделать и как вы хотите это сделать.

1 голос
/ 19 октября 2011

Я бы не советовал вам идти по маршруту, чтобы получить доступ к активной форме для достижения цели. Вам нужно передать ссылку на MainForm в OrderForm, чтобы OrderForm мог использовать эту ссылку для вызова любого метода в MainForm.

private void MainFrm_Load(object sender, EventArgs e)
{
     FormOrder frmO = new FormOrder();
     frmO.MainForm = this;

     frmO.Show();
}

А в классе FormOrder вы должны добавить новый атрибут MainForm и использовать этот атрибут для ссылки на форму вызова: -

public partial class FormOrder : Form
{
    public Form MainForm;

    public FormOrder()
    {
        InitializeComponent();
    }

    private void ShowForm()
    {
        // some action
    }

    private void btnCopy_Click(object sender, EventArgs e)
    {
        if (MainForm != null)
        {
            MainForm.Refresh();
        }

    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...