2009-09-13 4 views
0

System.Web.UI.Control에서 상속하는 사용자 지정 컨트롤이 있고 그 속성 중 일부는 데이터 바인딩 식을 사용하여 선언적으로 설정할 수 있습니다. 예 : 이제ASP.NET 컨트롤 속성에 데이터 바인딩식이 포함되어 있는지 확인하는 방법은 무엇입니까?

<foo:Foo runat="server" MyFoo="<%# this.GetFoo() %>" /> 

, 나는 이러한 식을 평가하기 위해 제어에 .DataBind() (또는 부모 중 하나)를 호출 할 필요가 있다고 할 때. 내가 할 수 있도록하고 싶습니다 무엇

는 어떤 속성이이 방법을 설정하고 단지 자동 약이 OnPreRender 또는 후 사용자 지정 컨트롤 호출 this.DataBind()이 있다면 감지 기능을 설정하는 메뉴입니다.

질문 : : 데이터 바인딩식이 실행되기를 기다리는 경우 어떻게 감지합니까?

일부 ControlBuilder 또는 DataBindContext 클래스에서이를 확인하는 데 필요한 정보가 있다고 확신합니다. 나는 반사경으로 사냥을 해봤고 그것을 발견 할 수없는 것처럼 보였다.

직접 속성이 할당되지 않은 경우 DataBind()을 실행하는 오버 헤드를 지불하고 싶지는 않습니다. 이것이 내가 전에 손에 들고 싶었던 이유입니다. 이 클래스는 매우 가볍지 만 코드가 필요없이 선언적으로 속성을 설정하는 기능을 원합니다.

+1

왜 단순히 코드 뒤에 Page.DataBind()를 사용하여 바인딩하지 않을까요?! 그것은 그 페이지의 모든 컨트롤을 무의식 중에 바인딩 할 것입니다 ... 참조 : http://support.microsoft.com.com/kb/307860 # 1b –

+0

필자는이 질문에서 DataBind()가 필요하지 않은 경우이를 실행하는 오버 헤드를 지불하고 싶지는 않습니다. – mckamey

답변

2

ControlBuilder을 더 자세히 살펴보면 데이터 바인딩 표현식이있을 때 각 컨트롤 인스턴스의 컴파일 된 팩토리에 DataBinding 이벤트 핸들러가 첨부된다는 것을 알았습니다. 나는 이것을 확인하는 것이 데이터 바인딩이 발생해야 하는지를 결정하는 매우 신뢰할만한 방법 인 것으로 보인다. 여기에 문제에 대한 내 솔루션의 기준은 다음과 같습니다

using System; 
using System.Reflection; 
using System.Web.UI; 

public class AutoDataBindControl : Control 
{ 
    private static readonly object EventDataBinding; 
    private bool needsDataBinding = false; 

    static AutoDataBindControl() 
    { 
     try 
     { 
      FieldInfo field = typeof(Control).GetField(
       "EventDataBinding", 
       BindingFlags.NonPublic|BindingFlags.Static); 

      if (field != null) 
      { 
       AutoDataBindControl.EventDataBinding = field.GetValue(null); 
      } 
     } 
     catch { } 

     if (AutoDataBindControl.EventDataBinding == null) 
     { 
      // effectively disables the auto-binding feature 
      AutoDataBindControl.EventDataBinding = new object(); 
     } 
    } 

    protected override void DataBind(bool raiseOnDataBinding) 
    { 
     base.DataBind(raiseOnDataBinding); 

     // flag that databinding has taken place 
     this.needsDataBinding = false; 
    } 

    protected override void OnInit(EventArgs e) 
    { 
     base.OnInit(e); 

     // check for the presence of DataBinding event handler 
     if (this.HasEvents()) 
     { 
      EventHandler handler = this.Events[AutoDataBindControl.EventDataBinding] as EventHandler; 
      if (handler != null) 
      { 
       // flag that databinding is needed 
       this.needsDataBinding = true; 

       this.Page.PreRenderComplete += new EventHandler(this.OnPreRenderComplete); 
      } 
     } 
    } 

    void OnPreRenderComplete(object sender, EventArgs e) 
    { 
     // DataBind only if needed 
     if (this.needsDataBinding) 
     { 
      this.DataBind(); 
     } 
    } 
} 

이 솔루션은 더 DataBinding 이벤트 처리기가 연결되지 않은 경우 자체를 불가능하게하거나 제어 (직접 또는 부모를 통해) 수동으로 데이터 바인딩을 경우.

이 코드의 대부분은 이벤트의 존재 여부를 테스트 할 수 있도록 농구대를 뛰어 넘는 것입니다. 유일한 반사는 EventDataBinding의 키로 object을 사용하기 위해 일회성 조회입니다.

0

ControlBuilder 클래스에는 SubBuilders이라는 internal ArrayList이 있습니다. 각 데이터 바인딩 식 TemplateParser enocunters의 경우 ProcessCodeBlock()BlockType 속성이 CodeBlockType.DataBinding에서 SubBuildersCodeBlockBuilder 개체를 추가합니다.

그래서 당신이 핸들을 얻을 수있는 경우 ControlBuilder 당신이 반사적으로 SubBuilders 반복 입력 CodeBlockBuilderBlockType == CodeBlockType.DataBinding의 객체를 찾을 수 있어야합니다.

물론 이것은 모든 종류의 불쾌한 점이며, 이것이 핵심 문제를 해결할 수있는 가장 좋은 방법이라는 점에 저는 의심합니다. 두 단계를 거쳐 원래의 문제를 살펴 본다면 아마도 Stackoverflow에 게시 할 것입니다. 훌륭한 솔루션을 찾는 데 도움이 될 수있는 많은 훌륭한 영리한 사람들이 있습니다.

+0

그게 원래의 문제였습니다. 때때로 데이터 바인딩 표현식이 나타났습니다. 컨트롤 자체가'DataBind'를 호출해야한다는 것을 의미하지 않으면 코드를 추가하지 않아도되고 싶습니다. 성능이 항상 'DataBind'가 될 수 있습니다. 나는 'System.Web.UI.WebControls.BaseDataBoundControl'이 자동 바인드하는 방법을 알고 있었지만,이 간단한 필요성 때문에 너무 무거웠다 고 생각했습니다. 실제 바인딩 정보를 추적하는 것보다 원하는 정보를 원했습니다. 실제 정보가 더 비싸게 들릴 수도 있지만 (리플렉션) 먼저 확인해 보겠습니다. 감사. – mckamey

관련 문제