2010-05-14 5 views
6

C# .NET에서 폼의 모달에 문제가 있습니다. 메인 폼 # 0이 있다고 가정 해 봅니다 (아래 이미지 참조). 이 양식은 사용자가 다양한 작업을 수행 할 수있는 주요 응용 프로그램 양식을 나타냅니다. 그러나 때로는 작업을 지원하는 추가 응용 프로그램 기능을 수행하기 위해 넌 모달 형식을 추가로 열 필요가 있습니다. 이것이 이미지의 형식 # 1이라고 가정 해 봅시다. 이 # 1 형식에서는 서로 위에 몇 개의 추가 모달 형식이 열릴 수 있으며 (이미지의 2 번 형식) 결국에는 긴 작업 진행 및 상태를 보여주는 진행 대화 상자가 표시됩니다. 최대 몇 시간까지. 문제는 모든 모달 양식 (이미지의 # 2)을 닫을 때까지 기본 양식 # 0이 반응하지 않는다는 것입니다. 이 양식에서 기본 양식 # 0이 작동해야합니다. 그러나 양식 # 2에서 비 모달 양식을 열면 모달 # 2 양식과 새로 만든 비 모달 양식으로 모두 작업 할 수 있습니다. 기본 양식 # 0과 양식 # 1 사이에 모든 하위 양식과 동일한 동작이 필요합니다. 가능한가? 아니면 내가 잘못하고있는거야? 어쩌면 대안의 어떤 종류가, 정말 ... ShowDialog를 보여 호출을 모두 변경WinForms 프로그래밍 - 모달 및 넌 모달 폼 문제

Image http://img225.imageshack.us/img225/1075/modalnonmodalproblem.png

+2

다른 양식 중 하나와 모달 만있는 양식을 만들 것을 요청합니까? – SLaks

+0

기본 모달 # 0은 모달이 아닌 폼 # 1을 몇 가지 추가 모달 자식 폼 (# 2)과 함께 열면 응답 성이 유지되기를 원합니다. – Povilas

답변

12

모달 형식은 모달과 정확히 동일하므로 응용 프로그램의 다른 모든 창을 비활성화합니다. 그것은 매우 중요합니다. 프로그램은 어느 정도 위험한 상태에 있습니다. 대화 상자가 닫힐 때까지 기다리는 코드 덩어리가 있습니다. 다른 창이 비활성화되어 있지 않으면 정말 나쁜 일이 일어날 수 있습니다. 사용자가 모달 대화 상자를 다시 시작할 수있는 것처럼 이제 코드는 두 번 중첩됩니다. 또는 그녀는 대화 상자의 소유자 창을 닫을 수 있습니다. 갑자기 사라집니다.

이들은 루프 내에서 Application.DoEvents()를 호출 할 때 실행되는 정확한 종류의 문제입니다. 다른 창을 비활성화하지 않고 모달로 동작하도록 양식을 가져 오는 한 가지 방법입니다. 예를 들어 :

Form2 mDialog; 

    private void button1_Click(object sender, EventArgs e) { 
     mDialog = new Form2(); 
     mDialog.FormClosed += (o, ea) => mDialog = null; 
     mDialog.Show(this); 
     while (mDialog != null) Application.DoEvents(); 
    } 

위험입니다.

모달 형식은 문제가 발생하지 않도록 설계된 방식으로 사용하는 것이 가장 좋습니다. 모달 형식을 원하지 않으면 모달 형식으로 만들지 말고 Show() 메서드를 사용하십시오. 이 닫히려고 알고 그 FormClosing 이벤트 구독하기 :

private void button1_Click(object sender, EventArgs e) { 
     var frm = new Form2(); 
     frm.FormClosing += new FormClosingEventHandler(frm_FormClosing); 
     frm.Show(); 
    } 

    void frm_FormClosing(object sender, FormClosingEventArgs e) { 
     var frm = sender as Form2; 
     // Do something with <frm> 
     //... 
    } 
+0

답장을 보내 주셔서 감사합니다. 메인 폼 # 0과 폼 # 1은 기본적으로 자신의 삶을 살고 서로 상호 작용하지 않기 때문에 별도의 GUI 스레드를 사용할 수 있다고 생각합니다. 양식 # 1은 별도의 응용 프로그램 일 수도 있습니다. 모달 양식이 필요하지만 양식 # 1 컨텍스트에서만 ShowDialog()를 Show()로 변경할 수 없습니다. 사용자는 양식 # 1에서 열린 모달 양식이 닫히지 않을 때까지 양식 # 1 (양식 # 1에만 해당)로 작업을 진행할 수 없습니다. – Povilas

3

같은 것을 할 것입니다 마음에 오는 첫번째 것은 좋아하지 않을 것이다. 양식 2를 실행 한 다음 양식 1에서 두 번째 양식의 닫힌 이벤트를 처리하여 양식을 다시 사용할 수있게하면 양식 1을 사용 불가능하게 할 수 있습니다. 쇼 대화 상자를 사용하여 모달 2를 열지 마십시오.

사용자 입장에서 볼 때 이것은 매우 번거롭기 때문에 MDI 응용 프로그램을 사용하여 단일 컨테이너 안에 모든 창을 가져다 볼 수 있습니다.

0

기본 프로세스는 동일한 프로세스 공간에있는 모달 대화 상자가 닫힐 때까지 반응하지 않습니다. 그것에 대한 해결 방법이 없습니다.

0

그것은 나에게 보이는 true로 양식 # 0 IsMdiContainer 속성을 설정 MDI 응용 프로그램을 사용할 수있다. 당신이 양식 Modal = true의 모든 것 귀하의 질문에 명시된대로 ShowDialog()를 사용

public partial class Form0 { 
    public Form0 { 
     InitializeComponent(); 
     this.IsMdiContainer = true; // This will allow the Form #0 to be responsive while other forms are opened. 
    } 

    private void button1_Click(object sender, EventArgs e) { 
     Form1 newForm1 = new Form1(); 
     newForm1.Parent = this; 
     newForm1.Show(); 
    } 
} 

:

그런 다음 모두 뭔가를 할 수 있습니다.

정의에 의하면, 모달 폼은 다음과 같습니다 양식이 모달로 표시되면, 아무런 입력 (키보드 또는 마우스 클릭) 모달 폼의 개체를 제외하고는 발생하지

. 프로그램은 다른 양식 입력이 발생할 수 있기 전에 모달 양식을 숨기거나 닫아야합니다 (대개 일부 사용자 조치에 대한 응답으로). 모달로 표시된 양식은 일반적으로 응용 프로그램의 대화 상자로 사용됩니다.

[(Modal)] 속성을 사용하면 메서드 또는 속성에서 가져온 양식이 모달로 표시되었는지 확인할 수 있습니다.

따라서 모달 형식은 사용자로부터 즉각적인 도움/상호 작용이 필요한 경우에만 사용해야합니다. 그렇지 않으면 모달 형식을 사용하면 아마도 잘못된 방향으로 가고 있다고 생각하게됩니다.

메인 폼을 MDI 컨테이너로 만들고 싶지 않다면 멀티 슬레이팅을 사용하는 것이 간단한 BackgroundWorker 클래스를 통한 하나의 해결책 일 것입니다. 따라서, 당신이해야 할 무엇인가

  • 는 등, 당신이 떨어져 당신의 기본 양식이 반응 만드는,하고 싶은
  • 무엇입니까 ... 디자인 냄새처럼 나에게 보인다 ?

당신이해야 할 일을 설명하면, 우리는 당신을 올바른 방향으로, 또는 적어도 더 나은 방향으로 안내 할 수 있습니다.

+0

답변 해 주셔서 감사합니다. 더 잘 설명하려고 노력하겠습니다. MDI 또는 Show()를 Show()로 변경하면 모달 양식 (사용자 정의 데이터 편집기)이 필요하고 사용자가 현재 양식으로 끝나지 않으면 계속 진행할 수 없으므로 해결되지 않습니다. 형태 # 1 문맥에서. 양식 # 1 사용자는 나중에 기본 양식 # 0에 필요한 일부 데이터로 작업합니다. 기본적으로 메인 폼 # 0과 폼 # 1은 자신의 삶을 살며 폼 # 1은 별도의 어플리케이션 일 수도 있습니다. # 0에서 양식 # 1이 데이터를 업데이트하는 몇 개의 싱글 톤 객체에서 데이터를 가져옵니다. – Povilas

+0

올해 절반 동안 모든 것이 좋았지 만 새로운 요구 사항으로 인해 사용자 정의 데이터 편집기로 작업하는 데 몇 시간이 걸릴 수있는 상황이있었습니다. 그래서 나는 Hans Passant가 제안하는 것을 사용할 수 있다고 생각합니다. 이것은 별도의 GUI 스레드입니다. 그리고 몇 개의 싱글 톤 객체를 통해 데이터를 동기화하십시오. – Povilas

-1

사실 대답은 매우 간단합니다. 시도해보십시오.

newForm.showDialog(); 

상위 양식에 액세스 할 수없는 상태에서 새 양식이 열립니다.