×
INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Contact US

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Students Click Here

Bizarre customized gridview issue (ASPX with C#)

Bizarre customized gridview issue (ASPX with C#)

Bizarre customized gridview issue (ASPX with C#)

(OP)
Hi,
I have what may be a rather complicated issue. I have an extended gridview control that I swear used to work all the time, but I went away for a while, came back, and it doesn't work anymore (I'm the sole programmer).

The extended gridview is designed so that it always shows a footer row (for inserting new rows). It loads and displays existing data correctly. If there are no rows, then adding the data works fine. But if I'm adding a new row to a gridview that already has existing rows, I get an issue where gvPhones.FooterRow is null, so it can't find the control I'm referencing.

Here's the extended gridview class (gotten from a stackoverflow page):

CODE --> C#

using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;

//https://stackoverflow.com/questions/994895/always-show-footertemplate-even-no-data/10891744#10891744
namespace WebForms.LocalCodeLibrary.Controls
{
    //modified from https://stackoverflow.com/questions/3437581/show-gridview-footer-on-empty-grid
    public class GridViewExtended : GridView
    {

        private GridViewRow _footerRow;
        [DefaultValue(false), Category("Appearance"), Description("Include the footer when the table is empty")]
        public bool ShowFooterWhenEmpty { get; set; }

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Browsable(false)]
        public override GridViewRow FooterRow
        {
            get
            {
                if ((this._footerRow == null))
                {
                    this.EnsureChildControls();
                }
                return this._footerRow;
            }
        }

        protected override int CreateChildControls(System.Collections.IEnumerable dataSource, bool dataBinding)
        {
            //creates all the rows that would normally be created when instantiating the grid
            int returnVal = base.CreateChildControls(dataSource, dataBinding);
            //if no rows were created (i.e. returnVal == 0), and we need to show the footer row, then we need to create and bind the footer row.
            if (returnVal == 0 && this.ShowFooterWhenEmpty)
            {
                Table table = this.Controls.OfType<Table>().First<Table>();
                DataControlField[] dcf = new DataControlField[this.Columns.Count];
                this.Columns.CopyTo(dcf, 0);
                //creates the footer row
                this._footerRow = this.CreateRow(-1, -1, DataControlRowType.Footer, DataControlRowState.Normal, dataBinding, null, dcf, table.Rows, null);
                if (!this.ShowFooter)
                {
                    _footerRow.Visible = false;
                }
            }
            return returnVal;
        }

        private GridViewRow CreateRow(int rowIndex, int dataSourceIndex, DataControlRowType rowType, DataControlRowState rowState, bool dataBind, object dataItem, DataControlField[] fields, TableRowCollection rows, PagedDataSource pagedDataSource)
        {
            GridViewRow row = this.CreateRow(rowIndex, dataSourceIndex, rowType, rowState);
            GridViewRowEventArgs e = new GridViewRowEventArgs(row);
            if ((rowType != DataControlRowType.Pager))
            {
                this.InitializeRow(row, fields);
            }
            else
            {
                this.InitializePager(row, fields.Length, pagedDataSource);
            }
            //if the row has data, sets the data item
            if (dataBind)
            {
                row.DataItem = dataItem;
            }
            //Raises the RowCreated event
            this.OnRowCreated(e);
            //adds the row to the gridview's row collection
            rows.Add(row);
            //explicitly binds the data item to the row, including the footer row and raises the RowDataBound event.
            if (dataBind)
            {
                row.DataBind();
                this.OnRowDataBound(e);
                row.DataItem = null;
            }
            return row;
        }

    }

} 

Here's the relevant stuff in the ASPX page:

CODE --> ASPX

<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="ContactEdit.aspx.cs" Inherits="WebForms.Directory.ContactEdit" %>
<%@ Register TagPrefix="gcctl" Namespace="WebForms.LocalCodeLibrary.Controls" Assembly="WebForms" %>
<asp:Content ID="Content1" ContentPlaceHolderID="Head" runat="server">
    <style>
    </style>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <div id="bodycontent" class="body-content">
        <h2><asp:Literal ID="formheader" runat="server" /></h2>

        <!-- Start: Main Customer section -->
        <asp:Panel ID="mainformcontent" runat="server" CssClass="formsection">
            <section id="mainform" class="simplelayoutform">
                <asp:TextBox id="customerid" type="hidden" runat="server" />
                <asp:TextBox id="contactid" type="hidden" runat="server" />
            </section>
        </asp:Panel>
        <!-- End: Main Customer section -->

        <!-- Start: Phones section -->
        <asp:SqlDataSource ID="gvPhonesDataSource" runat="server" OnInserted="gvPhonesDataSource_Inserted"
            ConnectionString="<%$ ConnectionStrings:ConnString %>" 
            SelectCommand="SELECT p.[CustomerPhoneID]
                        ,p.[CustomerID]
                        ,LTRIM(COALESCE(cc.FirstName,'') + ' ' + COALESCE(cc.LastName,'')) AS ContactFullName
                        ,p.CustomerContactID
                        ,p.PhoneTypeID
                        ,lp.PhoneType
                        ,p.[PhoneNumber]
                        ,p.[Extension]
                        ,p.[FormattedPhone]
                        ,p.[IsActive]
                        ,CASE WHEN p.LocationID IS NULL THEN CASE WHEN p.CustomerContactID IS NULL THEN 0 ELSE 1 END ELSE 2 END AS SortOrder
                    FROM [dbo].[Phones] p
                    LEFT JOIN dbo.Contacts cc ON p.CustomerContactID = cc.CustomerContactID
                    LEFT JOIN list.PhoneTypes lp ON p.PhoneTypeID = lp.PhoneTypeID
                    WHERE p.CustomerContactID = @CustomerContactID"
            DeleteCommand="DELETE FROM [dbo].[Phones] WHERE [CustomerPhoneID] = @CustomerPhoneID" 
            InsertCommand="INSERT INTO [dbo].[Phones] ([CustomerID]
                        , [CustomerContactID]
                        , [PhoneNumber]
                        , [Extension]
                        , [PhoneTypeID]
                        , LastModifiedByStaffID) 
                    VALUES (@CustomerID
                        , @CustomerContactID
                        , CASE WHEN COALESCE(@FormattedPhone, '')='' THEN NULL ELSE LTRIM(RTRIM(LEFT(dbo.RemoveNonNumeric(@FormattedPhone),10))) END
                        , CASE WHEN COALESCE(@FormattedPhone, '')='' THEN NULL ELSE CASE WHEN LTRIM(RTRIM(SUBSTRING(dbo.RemoveNonNumeric(@FormattedPhone),11,1000))) = '' THEN NULL ELSE LTRIM(RTRIM(SUBSTRING(dbo.RemoveNonNumeric(@FormattedPhone),11,1000))) END END
                        , @PhoneTypeID
                        , @StaffID)" 
            UpdateCommand="UPDATE [dbo].[CustomerPhones] 
                        SET [CustomerContactID] = @CustomerContactID
                        , [PhoneNumber] = CASE WHEN COALESCE(@FormattedPhone, '')='' THEN NULL ELSE LTRIM(RTRIM(LEFT(dbo.RemoveNonNumeric(@FormattedPhone),10))) END
                        , [Extension] = CASE WHEN COALESCE(@FormattedPhone, '')='' THEN NULL ELSE CASE WHEN LTRIM(RTRIM(SUBSTRING(dbo.RemoveNonNumeric(@FormattedPhone),11,1000))) = '' THEN NULL ELSE LTRIM(RTRIM(SUBSTRING(dbo.RemoveNonNumeric(@FormattedPhone),11,1000))) END END
                        , [PhoneTypeID] = @PhoneTypeID
                        , [IsActive] = @IsActive
                        , [DateModified] = getdate()
                        , [LastModifiedByStaffID] = @StaffID
                    WHERE [CustomerPhoneID] = @CustomerPhoneID">
            <SelectParameters>
                <asp:ControlParameter Name="CustomerContactID" Type="Int32" ControlID="contactid" PropertyName="Text" />
            </SelectParameters>
            <DeleteParameters>
                <asp:Parameter Name="CustomerPhoneID" Type="Int32" />
            </DeleteParameters>
            <UpdateParameters>
                <asp:ControlParameter Name="CustomerContactID" Type="Int32" ControlID="contactid" PropertyName="Text" />
                <asp:Parameter Name="FormattedPhone" Type="String" />
                <asp:Parameter Name="PhoneTypeID" Type="Int32" />
                <asp:Parameter Name="IsActive" Type="Boolean" />
                <asp:SessionParameter Name="StaffID" Type="Int32" SessionField="StaffID" />
                <asp:Parameter Name="CustomerPhoneID" Type="Int32" />
            </UpdateParameters>
            <InsertParameters>
                <asp:ControlParameter Name="CustomerID" Type="Int32" ControlID="customerid" PropertyName="Text" />
                <asp:ControlParameter Name="CustomerContactID" Type="Int32" ControlID="contactid" PropertyName="Text" />
                <asp:Parameter Name="PhoneTypeID" Type="Int32" />
                <asp:Parameter Name="FormattedPhone" Type="String" />
                <asp:SessionParameter Name="StaffID" Type="Int32" SessionField="StaffID" />
            </InsertParameters>
        </asp:SqlDataSource>

        <asp:Panel ID="phonesformcontent" runat="server" CssClass="formsection separate">
            <section id="phonesform" class="simplelayoutform">
                <h3>All Phones</h3>
                <gcctl:MyCheckBox ID="chkPhoneShowInactive" Text="Show Inactive?" Checked="false" AutoPostBack="true" OnCheckedChanged="chkPhoneShowInactive_CheckedChanged" runat="server" />
        	    <asp:label id="lblPhoneMessage" CssClass="responsemsg" runat="server" enableviewstate="False" />
                <gcctl:gridviewextended ID="gvPhones" runat="server" DataSourceID="gvPhonesDataSource"
                    AutoGenerateColumns="False" DataKeyNames="CustomerPhoneID" EmptyDataText="No phones on record."
                    CssClass="searchresultsgrid" ShowFooter="True" OnRowCommand="gvPhones_RowCommand" AllowSorting="True"
                    ShowFooterWhenEmpty="true" OnRowDataBound="gvPhones_RowDataBound">
                    <Columns>
                        <asp:BoundField DataField="CustomerPhoneID" InsertVisible="false" ReadOnly="true" Visible="False" />

                        <asp:TemplateField HeaderText="Phone Type" SortExpression="PhoneType">
                            <FooterTemplate>
                                <asp:DropDownList ID="cboPhoneTypeID" runat="server"
                                    DataSourceID="DataSourcePhoneTypes" DataTextField="PhoneType" DataValueField="PhoneTypeID"
                                    SelectedValue='<%# Bind("PhoneTypeID") %>'>
                                </asp:DropDownList>
                            </FooterTemplate>
                            <EditItemTemplate>
                                <asp:DropDownList ID="cboPhoneTypeID" runat="server"
                                    DataSourceID="DataSourcePhoneTypes" DataTextField="PhoneType" DataValueField="PhoneTypeID"
                                    SelectedValue='<%# Bind("PhoneTypeID") %>'>
                                </asp:DropDownList>
                            </EditItemTemplate>
                            <ItemTemplate>
                                <asp:Label ID="lblPhoneTypeID" runat="server" Text='<%# Bind("PhoneType") %>'></asp:Label>
                            </ItemTemplate>
                        </asp:TemplateField>
                        <asp:TemplateField HeaderText="Phone" SortExpression="PhoneNumber">
                            <FooterTemplate>
                                <asp:TextBox runat="server" Text='<%# Bind("FormattedPhone") %>' ID="txtPhone"></asp:TextBox>
                            </FooterTemplate>
                            <EditItemTemplate>
                                <asp:TextBox runat="server" Text='<%# Bind("FormattedPhone") %>' ID="txtPhone"></asp:TextBox>
                            </EditItemTemplate>
                            <ItemTemplate>
                                <asp:Label runat="server" Text='<%# Bind("FormattedPhone") %>' ID="lblPhone"></asp:Label>
                            </ItemTemplate>
                        </asp:TemplateField>
                        <asp:TemplateField HeaderText="Active?" SortExpression="IsActive">
                            <FooterTemplate>
                                <asp:CheckBox runat="server" Checked='<%# Bind("IsActive") %>' ID="chkPhoneIsActive"></asp:CheckBox>
                            </FooterTemplate>
                            <EditItemTemplate>
                                <asp:CheckBox runat="server" Checked='<%# Bind("IsActive") %>' ID="chkPhoneIsActive"></asp:CheckBox>
                            </EditItemTemplate>
                            <ItemTemplate>
                                <asp:Label runat="server" Text='<%# Bind("IsActive") %>' ID="lblPhoneIsActive"></asp:Label>
                            </ItemTemplate>
                        </asp:TemplateField>

                        <asp:TemplateField ShowHeader="False">
                            <EditItemTemplate>
                                <asp:LinkButton runat="server" Text="Update" CommandName="Update" CausesValidation="True" ID="PhoneUpdate"></asp:LinkButton>&nbsp;<asp:LinkButton runat="server" Text="Cancel" CommandName="Cancel" CausesValidation="False" ID="PhoneEditCancel"></asp:LinkButton>
                            </EditItemTemplate>
                            <ItemTemplate>
                                <asp:LinkButton runat="server" Text="Edit" CommandName="Edit" CausesValidation="False" ID="PhoneEdit"></asp:LinkButton>&nbsp;<asp:LinkButton runat="server" Text="Delete" CommandName="Delete" CausesValidation="False" ID="PhoneDelete"></asp:LinkButton>
                            </ItemTemplate>
                            <FooterTemplate>
                                <asp:LinkButton runat="server" Text="Save New Phone" CommandName="FooterInsert" CausesValidation="True" ID="PhoneInsert"></asp:LinkButton>
                            </FooterTemplate>
                        </asp:TemplateField>
                    </Columns>
                </gcctl:gridviewextended>
                <div id="phonenotes" class="tip">
                    <div>NUMBERS ONLY - NO LETTER CODES IN THE PHONE FIELD!</div>
                    <div>Be sure to always enter the area code, especially if you're also adding an extension.</div>
                    <div>Note that only numbers will stay in the "Phone" field. Anything else you enter will disappear once it goes behind the scenes. The first 10 digits will become the phone number, and any remaining digits will become the extension.</div> 
                </div>
            </section>
        </asp:Panel>
        <!-- End: Phones section -->
    
        <div id="responsetextdiv" class="error"><asp:Literal ID="responsetext" runat="server"></asp:Literal></div>
    
    </div>

    <asp:XmlDataSource ID="DataSourcePhoneTypes" runat="server" DataFile="~/XML/PhoneTypes.xml" EnableCaching="true">
    </asp:XmlDataSource>

</asp:Content> 

Here's the code where I get the error:

CODE --> C#

protected void gvPhones_RowCommand(object sender, GridViewCommandEventArgs e)
        {
            // Insert data if the CommandName == "Insert" 
            // and the validation controls indicate valid data...
            if (e.CommandName == "FooterInsert" && Page.IsValid)
            {
//ERROR HAPPENS ON THE FOLLOWING LINE:
                DropDownList PhoneTypeID = (DropDownList)gvPhones.FooterRow.FindControl("cboPhoneTypeID");
                TextBox FormattedPhone = (TextBox)gvPhones.FooterRow.FindControl("txtPhone");

                gvPhonesDataSource.InsertParameters["PhoneTypeID"].DefaultValue = PhoneTypeID.SelectedValue.ToString();

                string sFormattedPhone = null;
                if (!string.IsNullOrEmpty(FormattedPhone.Text))
                    sFormattedPhone = FormattedPhone.Text;
                gvPhonesDataSource.InsertParameters["FormattedPhone"].DefaultValue = sFormattedPhone;

                gvPhonesDataSource.InsertParameters["CustomerID"].DefaultValue = customerid.Text.ToString();
                gvPhonesDataSource.InsertParameters["CustomerContactID"].DefaultValue = contactid.Text.ToString();
                gvPhonesDataSource.InsertParameters["StaffID"].DefaultValue = System.Web.HttpContext.Current.Session["StaffID"].ToString();

                // Insert new record
                gvPhonesDataSource.Insert();
            }
        } 

The full error I get is:
Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.

Source Error:


Line 276: if (e.CommandName == "FooterInsert" && Page.IsValid)
Line 277: {
Line 278: DropDownList PhoneTypeID = (DropDownList)gvPhones.FooterRow.FindControl("cboPhoneTypeID");
Line 279: TextBox FormattedPhone = (TextBox)gvPhones.FooterRow.FindControl("txtPhone");
Line 280:

Source File: <snip> Line: 278

Stack Trace:


[NullReferenceException: Object reference not set to an instance of an object.]
GCWebForms.Directory.ContactEdit.gvPhones_RowCommand(Object sender, GridViewCommandEventArgs e) in <snip>ContactEdit.aspx.cs:278
System.Web.UI.WebControls.GridView.OnRowCommand(GridViewCommandEventArgs e) +137
System.Web.UI.WebControls.GridView.HandleEvent(EventArgs e, Boolean causesValidation, String validationGroup) +95
System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args) +49
System.Web.UI.WebControls.GridViewRow.OnBubbleEvent(Object source, EventArgs e) +146
System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args) +49
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +5450

-----

When stepping through (when trying to add a new row to a gridview that already has data in it), I found that gvPhones.FooterRow says that it's null.

Any help would be greatly appreciated! smile

Katie

RE: Bizarre customized gridview issue (ASPX with C#)

I do not know ASP.NET so here a wild guess - are you making an asyncronous call?

CODE --> c#

if (this._footerRow == null)
{
    if (AppSettings.EnableAsyncModelBinding) {
       using (page.Context.SyncContext.AllowVoidAsyncOperationsBlock()) 
       {
           EnsureChildControls();
           await page.GetWaitForPreviousStepCompletionAwaitable();
       }
    }
    else
    {
        EnsureChildControls();
    }       
    
    return this._footerRow;
} 

Red Flag This Post

Please let us know here why this post is inappropriate. Reasons such as off-topic, duplicates, flames, illegal, vulgar, or students posting their homework.

Red Flag Submitted

Thank you for helping keep Tek-Tips Forums free from inappropriate posts.
The Tek-Tips staff will check this out and take appropriate action.

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members! Already a Member? Login

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close