【问题标题】:Controls in ItemTemplate can't be called in Code Behind无法在代码隐藏中调用 ItemTemplate 中的控件
【发布时间】:2013-11-07 15:24:54
【问题描述】:

我有服务器控件,例如在另一个 gridview 的模板字段中带有 gridview 的弹出窗口:

  <asp:TemplateField HeaderText="Actions">
                <ItemTemplate>
                    <asp:Button ID="viewHoursButton" runat="server" Text="View Hours" OnClick="viewHoursButton_OnClick" />
                    <ajaxToolkit:ModalPopupExtender ID="viewHoursPopup" runat="server"
                        TargetControlID="viewHoursButton"
                        PopupControlID="viewHoursPanel"
                        CancelControlID="closeInfoPanelButton2"
                        DropShadow="true">
                    </ajaxToolkit:ModalPopupExtender>
                    <asp:Panel ID="viewHoursPanel" runat="server" CssClass="infoPanel">
                        <asp:Button ID="closeInfoPanelButton2" runat="server" Text="X" CssClass="closeInfoPanelButton"  />
                        <asp:Label ID="viewHoursLabel" runat="server" Text="Label"></asp:Label>
                        <asp:GridView ID="viewHoursGridView" runat="server" AllowPaging="True" AutoGenerateColumns="False"
                            DataSourceID="SqlDataSource6" DataKeyNames="NonScrumStoryId,PK_DailyTaskHours"
                            BackColor="#DEBA84" BorderColor="#DEBA84" BorderStyle="None" BorderWidth="1px"
                            CellPadding="3" CellSpacing="2" Width="94%" OnRowDeleting="viewHoursGridView_OnRowDeleting"
                            OnRowDataBound="viewHoursGridView_OnRowDataBound" CssClass="centerGridView">
                            <Columns>
                                <asp:BoundField DataField="ActivityDate" HeaderText="Activity Date" SortExpression="ActivityDate"
                                    DataFormatString="{0:MM/dd/yyyy}" />
                                <asp:BoundField DataField="Hours" HeaderText="Hours" SortExpression="Hours" />
                                <asp:BoundField DataField="Notes" HeaderText="Notes" SortExpression="Notes" />
                                <asp:BoundField DataField="CreateDate" HeaderText="Created Date" SortExpression="CreateDate"
                                    Visible="false" />
                                <asp:CommandField ShowDeleteButton="True" />
                            </Columns>
                            <FooterStyle BackColor="#F7DFB5" ForeColor="#8C4510" />
                            <HeaderStyle BackColor="#7fc041" Font-Bold="True" ForeColor="White" />
                            <PagerStyle ForeColor="#8C4510" HorizontalAlign="Center" />
                            <RowStyle BackColor="#FFF7E7" ForeColor="#8C4510" />
                            <SortedAscendingCellStyle BackColor="#FFF1D4" />
                            <SortedAscendingHeaderStyle BackColor="#B95C30" />
                            <SortedDescendingCellStyle BackColor="#F1E5CE" />
                            <SortedDescendingHeaderStyle BackColor="#93451F" />
                        </asp:GridView>
                        <asp:SqlDataSource ID="SqlDataSource6" runat="server" ConnectionString="<%$ ConnectionStrings:ApplicationServices %>"
                            SelectCommand="
                           SELECT [DailyTaskHours].[PK_DailyTaskHours]
                                ,[DailyTaskHours].[NonScrumStoryId]
                                ,[DailyTaskHours].[Hours]
                                ,[DailyTaskHours].[Notes]
                                ,[DailyTaskHours].[ActivityDate]
                                ,[DailyTaskHours].[CreateDate]
                            FROM [NonScrumStory]
                                ,[DailyTaskHours]
                            WHERE [DailyTaskHours].[NonScrumStoryId] = @nonScrumStoryId
                                AND [NonScrumStory].[PK_NonScrumStory] = @nonScrumStoryId
                            ORDER BY [ActivityDate] DESC
                            "
                            DeleteCommand="
                            DELETE
                            FROM [DailyTaskHours]
                            WHERE ([PK_DailyTaskHours] = @setDailyPKDeleteParam)
                            ">
                            <SelectParameters>
                                <asp:QueryStringParameter Name="nonScrumStoryId" Type="String" />
                            </SelectParameters>
                            <DeleteParameters>
                                <asp:QueryStringParameter Name="setDailyPKDeleteParam" Type="Int32" />
                            </DeleteParameters>
                        </asp:SqlDataSource>
                    </asp:Panel>
                    <asp:Button ID="addHoursButton" runat="server" Text="Add Hours" OnClick="addHoursButton_OnClick" />
                    <asp:Button ID="editButton" runat="server" Text="Edit" OnClick="editButton_OnClick" />
                    <asp:Button ID="deleteButton" runat="server" Text="Delete" OnClick="deleteButton_OnClick" />
                </ItemTemplate>
            </asp:TemplateField>

我无法将它们移出网格视图,因为调用弹出窗口必须正常工作。

但是我的代码无法识别 ItemTemplate 中的某些 ID:

protected void viewHoursButton_OnClick(object sender, EventArgs e)
{
    viewHoursPopup.Show();
    viewHoursGridView.DataBind();
}

例如,即使按钮在 ItemTemplate 中,_OnClick 方法仍然有效,但两个方法调用都无法识别:

我该如何解决这个问题?

【问题讨论】:

    标签: c# asp.net gridview itemtemplate


    【解决方案1】:
    protected void viewHoursButton_OnClick(object sender, EventArgs e)
    {
        var viewHoursPopup = parentGridView.FindControl("viewHoursPopup")
            as WebControl;
        var viewHoursGridView = parentGridView.FindControl("viewHoursGridView");
        if (viewHoursPopup != null && viewHoursGriView != null)
        {
             viewHoursPopup.Show();
            viewHoursGridView.DataBind();
        }
    }
    

    ...或...

    protected void viewHoursButton_OnClick(object sender, EventArgs e)
    {
        var viewHoursButton = (Button)sender;
        var viewHoursPopup = viewHoursButton.Parent.FindControl("viewHoursPopup")
            as WebControl;
        var viewHoursGridView = viewHoursButton.Parent.FindControl("viewHoursGridView");
        if (viewHoursPopup != null && viewHoursGriView != null)
        {
             viewHoursPopup.Show();
            viewHoursGridView.DataBind();
        }
    }
    

    为什么?

    ItemTemplates、RowTemplates、EditTemplates 等都嵌套在 webforms 所称的 NamingContainers 中。您无法访问这些控件,因为它们是在运行时动态注入的,它们的控件 ID 不会由代码隐藏的部分自动生成的类自动映射。

    有两种解决方案:

    1. 将模板的内容包装到用户控件中。该 UserControl 的代码隐藏将具有对未进一步嵌套到其他模板中的任何控件的编译时访问权限。要启用 UserControl 和包含它的父模板之间的交互,请在 UserControl 上公开事件和公共属性

    2. 使用 .FindControl(string controlID) 来“搜索”包含控件的当前模板以找到您要查找的控件。请务必在尝试对其调用任何内容之前检查它们是否为 null,并根据您打算对其调用的方法将它们转换为适当的类型。

    【讨论】:

    • 这适用于 viewHoursGridView.DataBind();但这并没有让我在弹出窗口中调用 show...知道为什么吗?
    • “它不允许我在弹出窗口中调用 show”——怎么回事?它不编译,还是在运行时失败?如果是后者,事件执行期间viewHoursPopup是否为null?
    • 好的,这看起来可能是一个选角问题——请参阅更新的答案。
    • @DavidTunnell - 请参阅我的回答,您需要转换为在GridView 的标记中声明的更具体的类型,因为FindControl() 返回一个Control 类型,而不是实际的特定类型你需要。
    • @danludwig - 是的,这是一个选角问题。这是var 的缺点,因为它可以编译,但不能在运行时工作,或者至少不能按预期工作。 :-)
    【解决方案2】:

    使用FindControl() 方法,但将它们转换为您在标记的ItemTemplate 声明中使用的更具体的类型,如下所示:

    protected void viewHoursButton_OnClick(object sender, EventArgs e)
    {
        var viewHoursPopup = parentGridView.FindControl("viewHoursPopup") as ModalPopupExtender;
        var viewHoursGridView = parentGridView.FindControl("viewHoursGridView") as GridView;
        if (viewHoursPopup != null && viewHoursGriView != null)
        {
            viewHoursPopup.Show();
            viewHoursGridView.DataBind();
        }
    }
    

    注意:FindControl() 返回一个Control,这对于调用.Show() 方法的对象来说太笼统了。如果无法成功执行转换,as 运算符将返回 null,因此稍后对 null 的检查将捕捉到这种情况。

    【讨论】:

    • +1,有那么一瞬间我没有意识到你不能在 Control 的基础上调用 .Show
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-10
    • 2023-04-02
    • 2011-02-22
    • 2010-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多