2010-01-07 4 views
0

저는 오랫동안 GridViews 및 DetailsViews에서 작업 해 왔지만 어제는 새로운 시나리오를 접했습니다.DetailsView FindControl()은 일부 포스트 백 이후에 null을 반환합니다.

ImageView (CommandName = "Insert")가있는 GridView에서 DetailsView의 모드를 삽입으로 변경합니다. 이후에는 DetailsView 내부에 DropDownList가 있는지 살펴보고 일부 항목을 동적으로 추가합니다. 잘 작동하지만 처음으로 ImageButton을 처음 누르면됩니다. 자세히보기에서 "취소"를 클릭하고 ImageButton을 다시 누르면 .FindControl() 메서드가 null을 반환합니다. 여기에서 직면 한 라이프 사이클 문제는 무엇입니까?

내가이 샘플을 만든

: (그렇지 않으면 렌더링되지 않습니다, 그것은 단지 위해 DetailsView에 데이터 소스를 바인딩은 Visual Studio에서 실행되도록하려면)

마크 업 :

<asp:GridView ID="gvCategory" runat="server" OnRowCommand="gvCategory_RowCommand"> 
    <Columns> 
    </Columns> 
    <EmptyDataTemplate> 
     <asp:ImageButton ImageUrl="~/images/add.png" ID="ibAdd" runat="server" CommandName="Insert" /> 
    </EmptyDataTemplate> 
    </asp:GridView> 
    <asp:DetailsView ID="dvCategory" runat="server" Width="150px" AutoGenerateRows="false" 
      AutoGenerateInsertButton="True" DataSourceID="LinqDataSource1"> 
    <Fields> 
     <asp:TemplateField HeaderText="foo"> 
      <InsertItemTemplate> 
       <asp:DropDownList ID="ddlCategory" runat="server" Width="150"></asp:DropDownList> 
      </InsertItemTemplate> 
     </asp:TemplateField> 
    </Fields> 
    </asp:DetailsView><asp:LinqDataSource ID="LinqDataSource1" runat="server" 
    ContextTypeName="WebApplication1.DataClasses1DataContext" 
    TableName="Categories"></asp:LinqDataSource> 

Codebehind가 :

protected void Page_Load(object sender, EventArgs e) 
    { 
     if (!Page.IsPostBack) 
     { 
      this.gvCategory.DataBind(); 
     } 

    } 

    protected void gvCategory_RowCommand(object sender, GridViewCommandEventArgs e) 
    { 
     if (e.CommandName == "Insert") 
     { 
      this.dvCategory.ChangeMode(DetailsViewMode.Insert); 
      DropDownList _ddlCat = (DropDownList)this.dvCategory.FindControl("ddlCategory"); 
      if (_ddlCat != null) 
      { 
       _ddlCat.Items.Clear(); 
       _ddlCat.Items.Add(new ListItem() { Text = "-- empty --", Value = "-1" }); 
      } 
     } 
    } 

또한 InsertItemTemplate이 아닌 ItemTemplate을 사용해 보았지만 동일한 결과가 나타납니다. ChangeMode-Method를 사용하면 DetailsView.CurrentMode == InsertMode가됩니다. 내가 생각할 수있는 유일한 것은 마크 업이 이미 ItemTemplate에 대해 생성되었으며 InsertMode로 모드를 변경해도 렌더링 된 마크 업 등에 영향을 줄 수 없다는 점입니다.

누구에게도 해결책이 있습니까? =)

답변

2

나는 당신이 올바른 길에 있다고 생각합니다. 모든 코드를 보지 않고 말하기는 어렵지만 기본적으로 리피터 유형 컨트롤에서 행의 렌더링 모드를 변경할 때마다 다시 렌더링해야 다시 렌더링 할 수 있습니다. FindControl이 NULL을 반환한다는 사실은 단 한 가지를 의미합니다. 컨트롤이 없습니다. 그것은 렌더링되지 않았 음을 의미합니다. 컨트롤 계층을 보면이를 확인할 수 있습니다.

그래서 처리기에서 취소 중입니까?

+0

위에 게시 된 코드는 문서화 된 상황을 재현하기에 충분합니다. 추가로 .DataBinds()가 작동하는지 살펴 보겠습니다. – citronas

+1

명시 적 dvCategory.DataBind() 모드를 변경 한 후 솔루션을 가져 왔습니다. 고마워, 내가 얼마나이 일을했는지 ​​모르겠다;) 혹시라도 .DataBind() 호출이 정확히 무엇을하는지 알고 계십니까? 왜 작동합니까? DetailsView가 새로운 마크 업을 생성하도록 강제 실행합니까? – citronas

+0

글쎄, 지금 당신은 어려운 질문을하고 있습니다. 솔직히, 확실하지는 않지만, 여기 있습니다. 마크 업이 렌더링되고 있다고는 생각하지 않지만,이 호출은 실제 컨트롤 계층 구조의 생성을 트리거하는 것입니다. 템플릿 컨트롤의 경우 한 번에 하나의 템플릿 만 생성됩니다. 즉, ItemTemplate 또는 EditTemplate 중 하나만 사용할 수 있지만 둘 다 사용할 수는 없습니다. 그런데 왜 이것이 첫 번째 호출을 작동합니까 ??? 확실하지 않다. – Bryan

관련 문제