Covert
Covert

Reputation: 491

Why e.findcontrol return null

I am trying to find a server control inside gridiview template field on row data bound but it returns null. Why ?

I am trying to find a

control which has runat attribute but it returns null.

Actually i am trying to load HTML text in this control.

protected void gvBidDetails_RowDataBound(object sender, GridViewRowEventArgs e)
{
    try
    {
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            var paraAgreement = e.Row.FindControl("paraAgreement") as Literal;
            paraAgreement.Text = "sahdbaskjdbasjbdjabsdbhasdbhasjbhdab<br/>sdbasdbhasdjabjdbasjdbjasbhdashhhdbasdbhab<br/>shdbhashbdashbdashdabshdbhasdbjabsdabsdbhasbhdashdbasd";
        }
    }
    catch (Exception ex)
    {
        Utility.Msg_Error(Master, ex.Message);
    }
}

.aspx

        <asp:TemplateField HeaderText='Finalized ?'>
            <ItemTemplate>
                <asp:LinkButton ID="btnFinalizedRecord" OnClick="btnFinalizedRecord_Click" runat="server" Text='<%# Convert.ToBoolean(Eval("IsFinalized")) == true? "": "Finalize" %>'
                    CssClass="" ToolTip="Finalize" CommandName="Finalize"
                    CommandArgument='<%#Eval("IsFinalized")%>' Enabled='<%# Convert.ToBoolean(Eval("IsFinalized")) == true? false: true %>'></asp:LinkButton>

                <ajax:confirmbuttonextender id="ConfirmButtonExtender1" runat="server" displaymodalpopupid="mpe2" targetcontrolid="btnFinalizedRecord">
                                    </ajax:confirmbuttonextender>
                <ajax:modalpopupextender id="mpe2" runat="server" popupcontrolid="pnlPopup2" targetcontrolid="btnFinalizedRecord" okcontrolid="btnYes"
                    cancelcontrolid="btnNo" backgroundcssclass="modalBackground">
                                    </ajax:modalpopupextender>
                <asp:Panel ID="pnlPopup2" runat="server" CssClass="modalPopup" Style="display: none">
                    <div class="header">
                        Are you sure to <b>Finalize</b>? 
                    </div>
                    <div class="body">

                        <asp:CheckBox ID="chkConfirmFinalize" runat="server" />
                        <%--<a href="TermsAndConditions.aspx" target="_blank">Agree with the Terms and Conditions</a>--%>

                        <p runat="server" id="paraAgreement">
                        </p>

                    </div>
                    <div class="Popupfooter" align="right">
                        <asp:Button ID="btnYes" Enabled="false" CssClass="btn btn-sm btn-danger btnYes" runat="server" Text="Yes" />
                        <asp:Button ID="btnNo" CssClass="btn btn-sm btn-primary" runat="server" Text="No" />
                    </div>
                </asp:Panel>
            </ItemTemplate>
        </asp:TemplateField>

Upvotes: 0

Views: 1364

Answers (2)

Tetsuya Yamamoto
Tetsuya Yamamoto

Reputation: 24957

Edit 1:

You're trying to cast FindControl result into Literal and it returns null due to the HTML paragraph server control recognized as System.Web.UI.HtmlControls.HtmlGenericControl and as keyword silently swallowed InvalidCastException below:

Unable to cast object of type 'System.Web.UI.HtmlControls.HtmlGenericControl' to type 'System.Web.UI.WebControls.Literal'.

Hence, the FindControl assignment should be like this example:

protected void gvBidDetails_RowDataBound(object sender, GridViewRowEventArgs e)
{
    try
    {
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            var paraAgreement = e.Row.FindControl("paraAgreement") as HtmlGenericControl;
            paraAgreement.InnerText = "[sample text]";
        }
    }
    catch (Exception ex)
    {
        Utility.Msg_Error(Master, ex.Message);
    }
}

Another way to find nested child controls by control ID is by doing recursive search throughout parent control using customized method (credits to @Win):

// taken from /a/15708885/6378815
public static Control FindControlRecursive(Control parentControl, string id)
{
   if (parentControl.ID == id) 
   {
       return parentControl;
   }

   return parentControl.Controls.Cast<Control>().Select(c => FindControlRecursive(c, id)).FirstOrDefault(c => c != null);
}

// GridView event method
protected void gvBindDetails_RowDataBound(object sender, GridViewRowEventArgs e)
{
    try
    {
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            var paraAgreement = new HtmlGenericControl();
            foreach (Control control in gvBindDetails.Rows)
            {
                paraAgreement = FindControlRecursive(control, "paraAgreement") as HtmlGenericControl;
            }

            paraAgreement.InnerText = "[sample text]";
        }
    }
    catch (Exception ex)
    {
        Utility.Msg_Error(Master, ex.Message);
    }
}

Additional reference:

System.Web.UI.HtmlControls.HtmlGenericControl (MSDN)

Related issues:

Find Controls nested inside Repeater Control

Better way to find control in ASP.NET

Upvotes: 2

VDWWD
VDWWD

Reputation: 35514

You are using FindControl to search for a Literal. But paraAgreement is not an actual asp:Literal Control. So it always return null.

Use HtmlGenericControl instead.

HtmlGenericControl p = e.Row.FindControl("paraAgreement") as HtmlGenericControl;
p.InnerHtml = "Found the Control";

Upvotes: 1

Related Questions