【问题标题】:DetailsView FindControl() returns null after some postbacksDetailsView FindControl() 在一些回发后返回 null
【发布时间】:2010-01-07 00:41:30
【问题描述】:

我已经使用 GridViews 和 DetailsViews 工作了很长时间,但是昨天我遇到了一个新场景,我很不明白。

我有一个带有 ImageButton (CommandName="Insert") 的 GridView,它会将 DetailsView 的模式更改为 Insert。之后,我将在该 DetailsView 中查找 DropDownList 并动态添加一些项目。工作正常,但第一次我第一次按下那个 ImageButton。如果我在 DetailsView 中单击“取消”并再次按下 ImageButton,.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 生成了标记,并且将 Mode 更改为 InsertMode 不会影响呈现的标记或类似的东西。

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

【问题讨论】:

    标签: c# asp.net gridview postback detailsview


    【解决方案1】:

    我认为你是在正确的轨道上。如果不查看所有代码很难判断,但基本上任何时候您更改中继器类型控件中一行的呈现模式时,您都需要重新绑定它以便重新呈现它。 FindControl 返回 NULL 的事实仅意味着一件事:控件不存在。这意味着它没有被渲染。您可以通过查看控件层次结构来验证这一点。

    那么,在您的 Cancel 处理程序中,您是否重新绑定?

    【讨论】:

    • 我上面贴的代码足以重现所描述的情况。我会尝试看看是否有一些额外的 .DataBinds() 可以工作。
    • 更改模式后的显式 dvCategory.DataBind() 带来了解决方案。谢谢你,你不知道我在这方面工作了多久;)你有没有机会知道 .DataBind() 调用的确切作用?为什么它有效?它会强制 DetailsView 生成新的标记吗?
    • 好吧,现在你问的是棘手的问题......老实说,不完全确定,但这是我的看法:我认为没有呈现任何标记,但这个调用是触发创建实际的控制层次结构。对于模板化控件,一次只创建一个模板:您可以拥有 ItemTemplate 或 EditTemplate,但不能同时拥有这两者。那么为什么这在第一次调用时起作用???不确定。
    • 顺便说一句,我想我应该在第一个答案中说“实例化”而不是“渲染”。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-20
    • 1970-01-01
    • 1970-01-01
    • 2019-01-09
    • 2013-03-16
    • 2012-08-18
    • 1970-01-01
    相关资源
    最近更新 更多