Подтвердить что ты не робот

Закрытие формы во время конструктора

Возможно ли закрыть форму при выполнении конструктора (или просто остановить ее показ на этом этапе)?

У меня есть следующий код:

public partial class MyForm : Form
{        
    public MyForm()
    {
        if (MyFunc())
        {
            this.Close();
        }
    }
}

Что вызывает ObjectDisposedException в Main(), здесь:

    static void Main()
    {            
        ...

        // Following line errors
        Application.Run(new MyForm());
    }

Ive попытался проверить результат MyForm следующим образом:

static void Main()
{            
    ...

    MyForm frm = new MyForm();
    if (frm != null)
    {
        // Following line errors
        Application.Run(frm);
    }
}

Но это, похоже, не помогает. Может ли кто-нибудь сказать мне об этом, пожалуйста? Может быть, способ проверить форму, чтобы увидеть, существует ли она еще?

4b9b3361

Ответ 1

Вызов Close из конструктора формы невозможен, так как он вызовет Dispose для формы, которая еще не была создана. Чтобы закрыть форму после создания, назначьте анонимный обработчик события Load, событие, которое закрывает форму до ее первого отображения:

public partial class MyForm : Form
{
    public MyForm()
    {
        if (ShouldClose())
        {
            Load += (s, e) => Close();
            return;
        }

        // ...
    }

    // ...
}

Ответ 2

Единственное, что вы могли бы сделать, это установить флаг, чтобы закрыть его в конструкторе, а затем закрыть его в событии Shown. Конечно, если вы это делаете, имеет смысл переместить код, чтобы определить, следует ли его закрывать в первую очередь.

Ответ 3

Хорошо работает следующее:

public partial class MyForm : Form
{        
    public MyForm()
    {
        if (MyFunc())
        {
            this.Shown += new EventHandler(MyForm_CloseOnStart);
        }
    }

    private void MyForm_CloseOnStart(object sender, EventArgs e)
    {
        this.Close();
    }
}

Ответ 4

Когда вы вызываете Close() в форме, внутренне она удаляет форму и освобождает любые управляемые ресурсы. Когда вы это сделаете:

Application.Run(new MyForm());

Вероятно, вы получите ObjectDisposedException. Что вам нужно сделать, это установить видимость формы через свойство:

Application.Run(new MyForm() { Visible = false });

Просто убедитесь, что вы удаляете вызов Close() в конструкторе или даже перемещаете его также.

Ответ 5

Можете ли вы сделать MyFunc статическим? и затем сделайте что-то вроде:

static void Main() 
{             
    ... 
    if (MyForm.MyFunc())
    {
        Application.Run(new MyForm()); 
    }
} 

это, по сути, даст вам тот же контроль над тем, будет ли форма создана или нет?

Ответ 6

Я обнаружил, что добавление обработчика в событие "Загрузить" лучше, так как диалог никогда не отображается вообще. С событием "Показываемое" вы можете в кратком диалоговом окне открыть диалоговое окно и закрыть его, что может сбить с толку:

public partial class MyForm : Form
{        
    public MyForm()
    {
        if (MyFunc())
        {
            this.Load += MyForm_CloseOnStart;
        }
    }

    private void MyForm_CloseOnStart(object sender, EventArgs e)
    {
        this.Close();
    }
}

Ответ 7

Ваша форма не будет открыта из конструктора. Чего вы пытаетесь достичь?

Если вы закроете эту форму, то путь к коду полностью завершится, что не даст вам очевидной выгоды (то есть Application.Run выйдет). Кто-то еще опубликовал код о скрытии формы, кажется более вероятным.

Ответ 8

Я думаю, что не стоит закрывать форму в конструкторе. Если вы сделаете это, пользователи вашей формы не будут знать, показывать ли ShowDialog или нет.

Следующий код будет вполне нормальным:

// in the parent form:
public void ShowMyForm()
{
    MyForm form = new MyForm();
    form.propertyA = ...;
    from.propertyB = ...;
    DialogResult dlgResult = form.ShowDialog(this);
    ProcessDialogResult(dlgResult);
}

Если в конструкторе вы решили, должна ли форма отображаться, вам нужно будет добавить код после построения, чтобы решить, вызывать ли ShowDialog или нет и обрабатывать ли результат диалога.

Кроме того, вы уверены, что изменение свойств никогда не повлияет на то, должна ли форма отображаться или нет? Также после будущих изменений?

Во время строительства форма еще не показана/не открыта. Поэтому я боюсь Close() не делает то, что вы ожидаете.

Аккуратный метод - делать проверки, которые вы хотели выполнить в конструкторе Form_Load. Добавьте обработчик событий для загрузки формы и выполните свои проверки в обработчике событий. Используйте свойство DialogResult, чтобы указать, что вы решили не показывать форму.

private void FormMain_Load (object sender, EventArgs e)
{
    if (FormShouldNotLoad())
    {
        this.DialogResult = System.Windows.Forms.DialogResult.Abort;
        Close();
        // Warning, this does not work, see below, (but we're almost there!)
    }
}

Пользователь кода может проверить результат диалога:

// in the parent form:
public void ShowMyForm()
{
    MyForm form = new MyForm();
    form.propertyA = ...;
    from.propertyB = ...;
    DialogResult dlgResult = form.ShowDialog(this);
    switch (dlgResult)
    {
        case System.Windows.Forms.DialogResult.Abort:
            ProcessFormNotLoaded();
            break;
        case System.Windows.Forms.DialogResult.OK:
            ProcessFormOk();
            break;
        // etc.
    }
}

Однако вызов Close() в обработчике событий для загрузки формы не будет работать, потому что Close() может быть правильно вызван только после завершения загрузки.

Поэтому вместо вызова Close() вам следует BeginInvoke закрыть функцию(), чтобы после завершения загрузки была вызвана функция Close:

private void FormMain_Load (object sender, EventArgs e)
{
    if (FormShouldNotLoad())
    {
        this.DialogResult = System.Windows.Forms.DialogResult.Abort;
        // invoke the Close function after Load completed
        this.BeginInvoke(new MethodInvoker( () => this.CancelLoading())
    }
}

Ответ 9

Environment.Exit(...) работает для меня (без мерцания окна):

public partial class MyForm : Form
{        
    public MyForm()
    {
        if (weShouldClose)
        {
            Environment.Exit(0);
        }
    }
}

Ответ 10

Если вы хотите, чтобы ваше окно никогда не было видно
(без мгновенного открытия мерцающих окон, а затем исчезнуть):

public new void Show()
{
    if (MyFunc())
        base.Show();
    else
        ; // dispose or whatever
}

Хотя Show(...) имеет 2 перегрузки, а ShowDialog(...) - 2.
Не работает для основной формы, которая открывается через Application.Run(). Но кто это сделает? Кроме того, существует возможность открыть основную форму без использования Application.Run().