2011-02-09 2 views
5

수년간 WebForms를 사용해 왔지만 필자는 때때로 이벤트 라이프 사이클에 대해 혼란스러워하고 있습니다. 이것은 상황이 그들이하는 방식으로 작동하는 이유를 더 잘 이해하기를 희망하면서 해결해야 할 문제가 아닙니다.하위 컨트롤이 컨테이너보다 먼저 초기화되는 이유는 무엇입니까?

을 Default.aspx :

<form> 
    <MyControls:UserControl1 runat="server"> 
</form> 

위해 UserControl1 : ASCX :

는 폼이 있다고 가정

<MyControls:UserControl2 runat="server"> 

OnInit의 이벤트가 아래와 같은 순서로 발생 :

UserControl2_OnInit 
UserControl1_OnInit 
Default_OnInit 

이것이 바로 저음질이 아닌가? 컨트롤이 생성 된 순서대로 Init 코드를 실행하면 안됩니까? 부모 컨트롤이 OnInit을 실행하기 전에 자식 속성을 초기화 할 수 있어야합니까? 즉, 마크 업에서 하위 컨트롤의 속성을 초기화 할 수는 있지만 부모 컨트롤이 OnInit 이벤트에서 사용할 수있는 자식 컨트롤의 속성을 동적으로 설정할 수있는 직접적인 방법은 없습니다. 내가하고 결국 한 무엇

이 같은 물건 :

override void UserControl2_OnInit() 
{ 
    NamingContainer.OnInit += new EvenHandler(UserControl1_ActualInit); 
} 
protected void UserControl2_ActualInit(..) { 
    // do actual init code here, which will occur before OnLoad but after it's parent 
    // OnInit 
} 

는 그래서는 극복 할 수없는 문제가되지 않습니다. 나는 그것이 왜 처음부터 문제인지 이해하지 못합니다.

아마도 OnInit 코드에서 모든 자식 컨트롤을 초기화 할 수 있기를 원할 수도 있습니다. 그럼 좋겠지 만 먼저 base.OnInit을 호출 할 수 있어야합니다. 대신에 모든 자식 컨트롤 OnInit 이벤트가 실행되도록하는 초기화 코드가 필요합니다. 그러나 이벤트 라이프 사이클은 그렇게 작동하지 않습니다. Init 이벤트는 순환 적으로 연결되지 않고 부모 이벤트를 독립적으로 실행하는 것으로 보이며 가장 안쪽 이벤트는 항상 먼저 실행됩니다. 그러나 반복적으로 단순히 체인으로 묶어 놓으면 인생이 훨씬 쉬워 질 것입니다. 그래서 주어진 상황에서 일을하기 전에 기본 이벤트를 호출 할 수도 있고하지 않을 수도 있습니다. 이 겉보기에 반 직관적 인 상황을 바람직하거나 필요로하는 부분이 없어지는 것이 있습니까?

+0

기본 클래스가 자녀보다 먼저 초기화되기 때문에 동의합니다. –

+2

질문에 대한 답변이 없지만 수명주기의이 단계에서 상위 또는 하위 컨테이너에 의존해서는 안된다는 지침이 있음을 알려드립니다. http://msdn.microsoft.com/en-us/library/system.web.ui.control.init.aspx –

+0

이것은 웹 폼 아키텍처의 근본적인 디자인 결함이라고 생각합니다. 그래서 부모님과 자식 컨트롤 사이의 관계를 'OnLoad'라고 가정 할 때까지는 가정하지 않습니다. 그러나 동적으로 생성 된 컨트롤을 다시 작성하는 것처럼 OnLoad 전에 작업하는 것이 중요합니다 (OnInit에서 수행해야한다고 말함 : http://support.microsoft.com/kb/317794). 정보가 필요한 경우 어떻게해야합니까? 데이터 소스가 부모에 의해 결정되는 경우는 무엇입니까? –

답변

2

This document은 수명주기 질문의 주요 원인이되어야합니다.

기본적으로 OnInit은 제어의 내부 초기화 후에서 을 발생시킵니다. 페이지 컨트롤은 초기화 된 첫 번째 컨트롤이므로 내부 초기화 과정에서 Designer.cs 파일에서 제공하는 순서대로 모든 하위 컨트롤이 초기화되므로 페이지의 OnInit 이벤트가 마지막에 호출 된 컨트롤이됩니다. 모든 하위 컨트롤이 초기화되고 OnInit 이벤트가 시작될 때까지 초기화가 완료되지 않았기 때문입니다.그래픽, 그것은 다음과 같습니다

Page internal init 
    Sub-control1 internal init 
     Sub-sub-control3 internal init 
     Sub-sub-control3 init finished/OnInit fired 
    Sub-control1 init finished/OnInit fired 
    Sub-control2 internal init 
    Sub-control2 init finished/OnInit fired 
Page init finished/OnInit fired 

그래서이 경우 inits의 순서는 다음과 같습니다

  1. 하위 하위 control3는
  2. 하위 제어 1은
  3. 하위 control2는
  4. 을하는 OnInit의 onInit의 onInit
  5. 페이지 OnInit

로드도 비슷하게 작동합니다. 일반적으로 대부분의 이벤트는 컨트롤이 먼저 내부 프로세스 (모든 하위 컨트롤에 동일한 이벤트를 호출하는 것을 포함)를 거쳐 처리 한 다음 나중에 사용자 지정 이벤트 처리 코드를 발생시키는 것처럼 처리해야합니다.

Page_Load는 대부분 해당 단계에서 호출되는 마지막 이벤트 여야하며 (즉, 포스트 백 데이터가로드 된 이후에) 사용해야합니다. Page_Load가 먼저 호출되고 사용자 정의 이벤트 처리 코드에 대해 완전히로드 된 상태가 아닌 컨트롤을 가질 위험이 있습니다.

1

asp.net 부모 & 자식 컨트롤에 대한 사고 방식은 다음과 같습니다

부모는 모든 자녀에 대해 알고 있지만, 아이들은 부모에 대한 아무것도을 알 수 없습니다.

이 사고 방식은 재사용 가능한 서버 컨트롤에 적합합니다. 재사용 성은 그것이 사용되는 페이지에 대한 가정을하지 않는 사용자 정의 하위 컨트롤을 필요로합니다.

귀하가 제공 한 스 니펫을 통해 자녀 사용자 컨트롤이 재사용을 목적으로하지 않는다고 추측 할 수 있습니다. 오히려 복잡한 & UI의 복잡성을 무너 뜨리는 데 사용하는 특수화 된 컨트롤입니까?

이 경우 나는 이 여전히 일 것입니다. '부모님에 대해 아무것도 모르는 아이들'과 함께 노력하십시오. http://www.google.co.uk/search?q=gof+mediator+pattern을 생각하십시오. 상위 페이지은 자녀 사이의 중재자입니다 (위키피디아 페이지는 좋습니다).

그러나 복잡한 UI 상호 작용을하고 있기 때문에 자녀가 여전히 부모 권한에 대해 알고 있어야합니다. 인터페이스로이를 해결할 수 있습니다. 각 자식은 부모에 의존하지 않고, 액세스 권한이 필요한 것을 정확하게 정의하는 인터페이스에 의존합니다. http://en.wikipedia.org/wiki/SOLID은 그것을 'concretions가 아니라 추상화에 의존합니다.'라고 말합니다. 하위 컨트롤 당 하나의 인터페이스를 사용하십시오. '많은 클라이언트 전용 인터페이스가 하나의 범용 인터페이스보다 낫습니다.'

하지만 모두 끝난 것 같습니다. 그렇지 않습니까? 구성 요소가 상호 작용해야하는 구성 요소 화 된 UI 인 은 단지이며 구성 요소가 크게 복잡해질 수 있습니다. 이것은 imho, MS 웹 양식 ajax가 jQuery를 잃어 버리는 것을 제어하는 ​​이유 중 하나입니다 & c. 심지어 전에 MVC가 나타납니다.

웹 양식 UI는 단위 테스트가 매우 어렵습니다. 소프트웨어 품질 다이브에 대한 자신감.

권장 사항 : 가능한 경우 MVC에서 다시 쓰기로 탈출하십시오. 그렇지 않으면 클라이언트 측 동작을 수행하는 서버 측 컨트롤을 포기하고 대신 jQuery를 사용하는 것이 좋습니다. 그렇게 할 수 없다면 간단히 단순화하여 UI를 단순화하십시오. 심지어 그것이 기능을 덜하게 만듭니다. 당신이 원하지 않는다면, 당신의 선택은 다음과 같습니다 : UI를 잘 엔지니어링하는 데 드는 비용을 지불하십시오; 또는 그것을 잘 조작하지 않는 비용을 지불해야합니다.

+0

사실, 나는 당신이 말하는 것을 거의 수행합니다 : 웹 폼을 피하십시오. 불행하게도 여전히 레거시 코드에 나타납니다 - 내 q.가 1 년 이상 되었더라도 부모님에 대한 지식이있는 아이는 내 질문에 구체적으로 포함되지 않습니다. 나는 왜 아이가 부모보다 먼저 초기화되는지를 알고 싶었습니다. 자식 지식은 기본적으로 종속성을 웹 폼에 생성하기 전에 삽입 할 수있는 기회가 없습니다. 생성 된 구문은 부모를 참조하는 자식을 포함하지만 부모에게 생성자에 대한 액세스 권한을 부여하는 메커니즘으로 만 사용됩니다. –

+0

여기에 동일 . Webforms will 수년 동안 우리와 함께하십시오. 어느 것이 내가이 Q를 우연히 발견했는지, 단위 테스트에서 페이지를 인스턴스화하고 테스트 할 수있는 범위 내에서 컨트롤 수명주기 주제를 검색하고있었습니다. 나는 자식 컨트롤에 붙어있어. 그러나 아이 생성자에 환경에 대해 알 필요가있는 증상을 주입하려고하지 않습니까? –

+0

어쩌면 저는 "환경"에 대한 당신의 요점을 오해하고 있습니다. 'sum (a, b)'는 그것이 합쳐질 두 가지를 알아야하는 클래스입니다. 그러나 건설 현장에서 정보가 제공됩니다. 그것은 외부의 무언가로부터 그것을 요구하지 않습니다. 마크 업에서 전달 된 컴파일 타임 속성의 경우를 제외하고는 사용자 정의 컨트롤을 사용하여 작업을 수행 할 수도 없습니다. 따라서 기본적으로 "사용자 정의 컨트롤은 사용자가 어떤 식으로도 구성 할 수 없다"는 것을 의미하는 경우 그렇습니다 ... 그것이 그 방법입니다 ... 그러나 그것은 완전한 원칙이 아닙니다. 단지 유용하지 않게 만듭니다. –

관련 문제