2010-01-05 6 views
4

컨트롤의 Visible 속성 가져 오기는 컨트롤을 렌더링할지 여부를 나타 내기 위해 반복적으로 트리를 찾습니다.Asp.Net에서 Visible 속성의 설정/실제 값을 얻는 방법

컨트롤의 "로컬"가시 값이 부모 컨트롤의 설정에 관계없이 무엇인지 확인하는 방법이 필요합니다. 즉, 그 자체가 참 또는 거짓으로 설정되었는지의 여부.

이 질문은 로컬 상태를 얻기 위해 Reflection을 사용하는 How to get the “real” value of the Visible property?입니다. 그러나 WebControls에서이 작업을 수행 할 수 없었습니다. 그것은 또한 가치를 얻는 다소 더러운 방법입니다.

나는 다음 확장 방법을 생각해 냈습니다. 부모로부터 컨트롤을 제거하고 속성을 확인한 다음 컨트롤을 찾은 곳으로 되돌려 놓습니다.

public static bool LocalVisible(this Control control) 
    { 
     //Get a reference to the parent 
     Control parent = control.Parent; 
     //Find where in the parent the control is. 
     int index = parent.Controls.IndexOf(control); 
     //Remove the control from the parent. 
     parent.Controls.Remove(control); 
     //Store the visible state of the control now it has no parent. 
     bool visible = control.Visible; 
     //Add the control back where it was in the parent. 
     parent.Controls.AddAt(index, control); 
     //Return the stored visible value. 
     return visible; 
    } 

이 방법을 사용할 수 있습니까? 그것은 잘 작동하고 나는 성능 문제를 가로 질러 오지 않았다. 그것은 단지 매우 더러운 것처럼 보입니다. 그리고 실제로 실패 할 수도있는 인스턴스가있을 수 있습니다 (예를 들어, 실제로 렌더링 할 때).

누구든지이 솔루션에 대한 의견이 있거나 더 나은 가치를 찾는 더 좋은 방법이 있다면 좋을 것입니다.

+0

반사 방식을 사용할 때 어떤 문제가 발생합니까? – slugster

+0

GetState의 GetMethod는 System.Web.UI.Control에 대해 null을 반환합니다. –

답변

3

조금 주위에 파고 후, 나는 System.Web.UI.Control에서 상속 클래스의 Visible 플래그의 값 검색하는 반사를 사용하는 다음 확장 메서드 생산 :

public static bool LocalVisible(this Control control) 
{ 
    var flags = typeof (Control) 
     .GetField("flags", BindingFlags.Instance | BindingFlags.NonPublic) 
     .GetValue(control); 

    return ! (bool) flags.GetType() 
     .GetProperty("Item", BindingFlags.Instance | BindingFlags.NonPublic) 
     .GetValue(flags, new object[] {0x10}); 
} 

그것은 민간 분야를 찾기 위해 반사를 사용을 flagsControl 개체 내에 이 필드는 내부 형식으로 선언되므로 인덱서 속성의 getter를 호출하는 데 더 많은 정보가 필요합니다.

확장 방법은 다음과 같은 마크 업에서 테스트되었습니다 :

<asp:Panel Visible="false" runat="server"> 
    <asp:Literal ID="litA" runat="server" /> 
    <asp:Literal ID="litB" Visible="true" runat="server" /> 
    <asp:Literal ID="litC" Visible="false" runat="server" /> 
</asp:Panel> 

<asp:Literal ID="litD" runat="server" /> 
<asp:Literal ID="litE" Visible="true" runat="server" /> 
<asp:Literal ID="litF" Visible="false" runat="server" /> 

테스트 결과 :

litA.LocalVisible() == true 
litB.LocalVisible() == true 
litC.LocalVisible() == false 
litD.LocalVisible() == true 
litE.LocalVisible() == true 
litF.LocalVisible() == false 
+0

+1 고마워요, 그게 내가 한 일 이었어. 그래도 이걸 쉽게 찾을 수있는 방법이 틀림 없음! –

+0

+1, 좋은 답변입니다. Visible 속성에서 리플렉션을 사용하면 get 접근자를 호출하기 때문에 사설 필드를 따라 가야합니다. 그곳에있는 논리가 무엇이든지간에. ASP.NET 컨트롤이 컨트롤 트리에서 표시 여부를 확인하는 것은 매우 드문 일이지만 Visible 속성이 false 인 경우 Render 메서드가 호출되지 않아도됩니다 (즉, 모든 자식 컨트롤이 자동으로 어느 쪽인지). – slugster

+0

@slugster : 그렇게하는 것은 매우 드문 일이지만 ASP.NET 컨트롤은 Visible 속성에서 getter를 호출 할 때 컨트롤 트리를 탐색합니다. 'Visible' 속성에 대한 내 대답에 표시된 테스트 사례를 실행하면 false, false, false, true, true, false가 표시됩니다. –

0

당신은 속성을 사용하여 컨트롤의 표시 여부를 노출 할 수 있습니다. 이것은 당신의 문제를 해결할 수 있습니다.

내가 잘못하면 저를 교정하십시오.

0

누군가가 VB.NET에서 작동하는 Jørn Schou-Rode의 코드를 얻으 려하면, 여기 저에게 적합한 코드가 있습니다. VB에서 코드를 번역 할 때 "Item"속성의 세 가지 맛이 있기 때문에 "모호한 일치가 발견되었습니다"예외가 발생합니다.

<Extension()> 
Public Function GetLocalVisible(ctl As Control) As Boolean 
    Dim flags As Object = GetType(Control).GetField("flags", BindingFlags.Instance Or BindingFlags.NonPublic).GetValue(ctl) 
    Dim infos As PropertyInfo() = flags.GetType().GetProperties(BindingFlags.Instance Or BindingFlags.NonPublic) 
    For Each info As PropertyInfo In infos 
     If info.Name = "Item" AndAlso info.PropertyType.Name = "Boolean" Then 
      Return Not CBool(info.GetValue(flags, New Object() {&H10})) 
     End If 
    Next 
    Return ctl.Visible 
End Function 
관련 문제