2010-06-11 3 views

답변

5

가장 확실한 방법은 양식 인스턴스의 수명을 추적하는 것입니다. FormClosed 이벤트를 구독하여 그렇게하십시오. 양식의 이름을 알고있는 경우

private UserForm userFormInstance; 

    private void showUserForm_Click(object sender, EventArgs e) { 
     if (userFormInstance != null) { 
      userFormInstance.WindowState = FormWindowState.Normal; 
      userFormInstance.Focus(); 
     } 
     else { 
      userFormInstance = new UserForm(); 
      userFormInstance.MdiParent = this; 
      userFormInstance.FormClosed += (o, ea) => userFormInstance = null; 
      userFormInstance.Show(); 
     } 
    } 
0

당신은 항상 A 형 싱글 만들 수 있습니다 : 당신은 당신의 폼 인스턴스를 관리하기위한 싱글 클래스를 만들어야합니다

MyForm.Instance.Show(); 
MyForm.Instance.MdiParent = this; 
+0

고정은 암호. 당신은 아무 것도 반환하지 않았고 접근자를 추가하지 않았습니다. – GenericTypeTea

+0

@GenericTypeTea - Heh. 화재 훈련에 갇혀서 코드를 편집하지 못했습니다. 감사! –

4

:

public class MyForm : Form 
{ 
    private MyForm _instance = null; 
    private object _lock = new object(); 

    private MyForm() { } 


    public static MyForm Instance 
    { 
     get 
     { 
      if (_instance == null) 
      { 
       lock (_lock) 
       { 
        if (_instance == null) 
        _instance = new MyForm(); 
       } 
      } 
      return _instance; 
     } 
    } 
} 

그런 다음 호출이 같이 보일 것을

public class FormProvider 
{ 
    public static UserForm UserForm 
    { 
     get 
     { 
      if (_userForm== null || _userForm.IsDisposed) 
      { 
      _userForm= new UserForm(); 
      } 
      return _userForm; 
     } 
    } 
    private static UserForm _userForm; 
} 

NB, 이것은 av ery 간단한 싱글 톤 패턴. 패턴을 올바르게 사용하려면 link을 사용하십시오.

다음과 같이 그럼 그냥 양식에 액세스 할 수는 :

FormProvider.UserForm가 처음으로 액세스 할
FormProvider.UserForm.Show(); 
FormProvider.UserForm.MdiParent = this; 

, 작성됩니다. 이후에 FormProvider.UserForm 등록 정보를 가져 오면 첫 번째 액세스시 작성된 양식이 리턴됩니다. 즉, 양식은 한 번만 생성됩니다.

+0

폼 인스턴스 주위에'lock '을 추가하는 것은 안전성을 추가하지 않고 단지 그것의 환영 만 추가합니다. 양식은 생성 된 스레드에서만 양식에 액세스 할 수 있으며 양식 *을 작성하려면 STA 스레드 여야합니다. syncronization을 추가하는 것은 논란의 여지가 있지만, 사용자가 실제로이 멀티 스레드 호환을 위해 필요한 작업을하고 있다는 인상을주기 때문에, 빠져 나가는 것보다 위험합니다. 또한 이것은 싱글 톤 (Singleton)을 요구하는 시나리오가 아닌 * *입니다. 마지막으로, 배치 된 객체에 액세스 할 때 양식이 닫히면 오류가 발생합니다. –

+0

정적 양식을 사용할 때 메모리 누수를 매우 잘 알고 있어야합니다. 양식의 이벤트 처리에 대한 자세한 내용은 http://msdn.microsoft.com/en-us/library/ee658248.aspx를 참조하십시오. –

+0

@Adam - 양식을 닫으면 오류가 발생하지 않습니다. 나는 거기에 2/3 소형 프레임 워크 애플 리케이션을 가지고 있고 문제가 없었습니다. 스레드 안전성에 관해 당신과 동의하십시오, 그래서 스 니펫을 제거했습니다. – GenericTypeTea

0

옵션 :

일반적으로, 버튼을 비활성화하는 것은 잘 작동 등을 만든다 사용자의 관점에서 싱글 톤은 다른 버튼을 활성화 한 버튼이 필요한 경우 작동합니다.

싱글 톤은 아마도 이 아니며 양식이 닫힐 수 있고 나중에 새 인스턴스가 필요하면 좋은 해결책입니다.

+0

버튼을 활성화 된 상태로두면 (이미 본 대부분의 응용 프로그램에서) 양식이 표시되거나 이미 열려있는 경우 가져 오게됩니다. –

4

기존 답변과 달리 이 아니고은 여기에 싱글 톤을 사용하는 것이 좋습니다. Singleton 패턴은 비참하게 남용되어 일반적으로 무언가가 전체 디자인에 잘못되었다는 것을 나타내는 "코드 냄새"입니다. 싱글 톤은 일반적으로 전역 변수와 동일한 "버킷 (bucket)"에 저장됩니다.이를 사용하는 것이 훨씬 낫습니다.

가장 간단한 해결책은 주 폼에서 문제의 폼을 나타내는 인스턴스 변수를 만든 다음이를 사용하여 인스턴스 변수를 표시하는 것입니다.

public class MainMdiForm : Form 
{ 
    ... 

    UserForm userForm; 

    ... 

    private void ShowUserForm() 
    { 
     if(userForm == null || userForm.IsDisposed) 
     { 
      userForm = new UserForm(); 
      userForm.MdiParent = this; 
     } 

     userForm.Show(); 
     userForm.BringToFront(); 
    } 
} 
+0

+1 싱글 톤을 사용하지 않는 경우 +1 –

+0

@Adam - 싱글 톤 패턴의 사용법이 잘못되었습니다. 그러나 이것은 싱글 톤이 올바르게 사용되는 특별한 경우 중 하나라고 생각합니다. 당신이하는 일은 사실상 싱글 톤 내에서 일어나는 것과 거의 동일합니다. 단지 당신이 더 복잡한 코드로 끝날 것입니다. – GenericTypeTea

+0

@ 일반 : 단일 인스턴스 만 생성하는 것은 싱글 톤이되는 객체의 동의어가 아니며 싱글 톤 패턴이 적절하다는 표시도 아닙니다. –

0

호스트 폼의 MdiChildren 속성을 검사하여 사용자 정의 폼의 인스턴스가 있는지 확인할 수 있습니다.

UserForm myForm = null; 
foreach (Form existingForm in this.MdiChildren) 
{ 
    myForm = existingForm as UserForm; 
    if (myForm != null) 
     break; 
} 

if (myForm == null) 
{ 
    myForm = new UserForm(); 
    myForm.MdiParent = this; 

    myForm.Show(); 
} 
else 
    myForm.Activate(); 

사용자 폼의 새 인스턴스를 만듭니다.이 인스턴스는 이미 존재하지 않으며 존재하는 경우 생성 된 인스턴스로 전환됩니다.

3

는 : 예를 들어

if (Application.OpenForms["FormName"] == null) 
     { 
      Form form = new Form(); 
      form.MdiParent = this; 
      form.Show(); 
     } 
     else 
      Application.OpenForms["FormName"].Focus(); 
0

이것은 aboutToolStripMenuItem_Click (내 ShowForm (용액) 및 호출 샘플)입니다 :

private void ShowForm(Type typeofForm, string sCaption) 
    { 
     Form fOpen = GetOpenForm(typeofForm); 
     Form fNew = fOpen; 
     if (fNew == null) 
      fNew = (Form)CreateNewInstanceOfType(typeofForm); 
     else 
      if (fNew.IsDisposed) 
       fNew = (Form)CreateNewInstanceOfType(typeofForm); 

     if (fOpen == null) 
     { 
      fNew.Text = sCaption; 
      fNew.ControlBox = true; 
      fNew.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; 
      fNew.MaximizeBox = false; 
      fNew.MinimizeBox = false; 
      // for MdiParent 
      //if (f1.MdiParent == null) 
      // f1.MdiParent = CProject.mFMain; 
      fNew.StartPosition = FormStartPosition.Manual; 
      fNew.Left = 0; 
      fNew.Top = 0; 
      ShowMsg("Ready"); 
     } 
     fNew.Show(); 
     fNew.Focus(); 
    } 
    private void aboutToolStripMenuItem_Click(object sender, EventArgs e) 
    { 
     ShowForm(typeof(FAboutBox), "About"); 
    } 

    private Form GetOpenForm(Type typeofForm) 
    { 
     FormCollection fc = Application.OpenForms; 
     foreach (Form f1 in fc) 
      if (f1.GetType() == typeofForm) 
       return f1; 

     return null; 
    } 
    private object CreateNewInstanceOfType(Type typeofAny) 
    { 
     return Activator.CreateInstance(typeofAny); 
    } 

    public void ShowMsg(string sMsg) 
    { 
     lblStatus.Text = sMsg; 
     if (lblStatus.ForeColor != SystemColors.ControlText) 
      lblStatus.ForeColor = SystemColors.ControlText; 
    } 
    public void ShowError(string sMsg) 
    { 
     lblStatus.Text = sMsg; 
     if (lblStatus.ForeColor != Color.Red) 
      lblStatus.ForeColor = Color.Red; 
    } 
관련 문제