2010-01-07 121 views
0

我一直在使用GridViews和DetailsViews很长一段时间,但是昨天我遇到了一个新的场景,我很不明白。我有一个GridView与ImageButton(CommandName =“插入”),这将改变DetailsView的模式插入。之后我会在DetailsView中查找DropDownList并动态添加一些项目。工作正常,但首先我第一次按下ImageButton。如果我在DetailsView中单击“取消”并再次按下ImageButton,则.FindControl()方法返回null。我在这里面临什么样的生命周期问题?DetailsView FindControl()在返回后返回null

我创造了这个样本:(使它在Visual Studio中运行,只要绑定一个DataSource到DetailsView控件,否则将不会被渲染)

标记:

<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> 

代码隐藏:

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" }); 
      } 
     } 
    } 

我也使用的ItemTemplate尝试,而不是一个InsertItemTemplate元素,但这会导致相同的。在使用ChangeMode-Method之后,DetailsView.CurrentMode == InsertMode。我唯一能想到的是,标记已经为ItemTemplate生成,并且将模式更改为InsertMode不会影响呈现的标记,或者类似的东西。

有没有人有解决这个问题? =)

回答

2

我认为你是在正确的轨道上。很难说没有看到所有的代码,但基本上每当你改变一个中继器类型控制中的行的渲染模式时,你需要重新绑定它以便重新渲染。 FindControl返回NULL的事实意味着只有一件事:控制不在那里。这意味着它没有呈现。您可以通过查看控制层次来验证这一点。

那么,在您的处理程序取消你重新绑定?

+0

我上面发布的代码足以重现所描述的情况。我会尝试查看一些额外的.DataBinds()是否可以工作。 – citronas 2010-01-07 03:02:19

+1

更改模式后显式dvCategory.DataBind()带来了解决方案。谢谢你,你不知道我在这工作了多长时间;) 你有没有机会知道.DataBind()调用到底做了什么?它为什么有效?它是否强制DetailsView生成新的标记? – citronas 2010-01-07 03:04:41

+0

好吧,现在你问的是棘手的问题......老实说,并不完全确定,但这里是我的看法:我不认为有任何标记正在渲染,但是这个调用触发了实际控制层次的创建。对于模板控件,一次只创建一个模板:您可以具有ItemTemplate或EditTemplate,但不能同时拥有两个模板。那么为什么这个工作的第一个电话?不确定。 – Bryan 2010-01-07 20:33:46