无法在Code Behind中调用ItemTemplate中的控件

时间:2013-11-07 15:24:54

标签: c# asp.net gridview itemtemplate

我有服务器控件,例如在另一个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>

我无法将它们移出gridview,因为弹出窗口的调用必须正常工作。

但是我的代码背后还没有识别ItemTemplate中的一些ID:

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

例如,即使按钮位于ItemTemplate内部,_OnClick方法仍可正常工作,但无法识别两个方法调用:

enter image description here

如何解决此问题?

2 个答案:

答案 0 :(得分:4)

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和包含它的父模板之间启用交互,请在UserControl上公开事件和公共属性

  2. 使用.FindControl(字符串controlID)“搜索”包含控件的当前模板,以查找您要查找的控件。确保在尝试调用它们之前检查它们是否为null,并根据您要在它们上调用的方法将它们强制转换为适当的类型。

答案 1 :(得分:1)

使用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将捕获该情况。