2010-06-18 4 views
37

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

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

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

Который бросает ObjectDisposedException в Main(), здесь:

static void Main() 
    {    
     ... 

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

Я пытался проверить результат MyForm так:

static void Main() 
{    
    ... 

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

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

+0

Какое исключение вы получаете? –

ответ

66

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

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

     // ... 
    } 

    // ... 
} 
+8

+1, просто замените Показывать с загрузкой без мерцания, и у вас есть победитель – Dialecticus

+0

@Dialecticus: Спасибо. Готово! – Christian

+0

Это дает мне эту ошибку: «Значение Close() не может быть вызвано при создании CreateHandle()« – GuidoG

2

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

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

4

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

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

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

9

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

Application.Run(new MyForm()); 

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

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

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

20

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

18

следующие работы: а

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

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

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

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

Я думаю, что это не разумно, чтобы закрыть форму в конструкторе.Если вы сделаете это, пользователи вашей формы не будут знать, показывать ли 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.Cancel; 
     Close(); 
    } 
} 

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

// 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.Cancel: 
      ... 
      break; 
     case System.Windows.Forms.DialogResult.OK: 
      ... 
      break; 
     // etc. 
    } 
} 

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

Код для завершения операции Close() после завершения загрузки будет следующим:

private void FormMain_Load (object sender, EventArgs e) 
{ 
    if (MyFunc()) 
    { 
     CancelLoading(); 
    } 
} 

private delegate void InvokeDelegate(); 

private void CancelLoading() 
{ // will cancel loading this form 
    this.DialogResult = System.Windows.Forms.DialogResult.Cancel; 
    this.BeginInvoke(new InvokeDelegate(CloseThisForm)); 
} 

private void CloseThisForm() 
{ 
    this.Close(); 
} 

Хорошо, что во время OnFormClosing и OnFormClosed вы точно знаете статус формы: она полностью загружена, поэтому вы знаете, что делать при закрытии.

+0

Это должен быть принятый ответ, принятый в настоящее время ответ компилируется, но дает ошибку времени выполнения. – GuidoG

1

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

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

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