Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

asp.net c# System.NullReferenceException

Posted on 2004-10-12
3
Medium Priority
?
1,075 Views
Last Modified: 2013-11-25
My code throws a System.NullReferenceException when I click the add_category button. However, the dataset that is bound to my datagrid should be initialised (see method Page_Load). When the site is loaded the first time the BindGrid() method should be invoked and initialize the dataset object.

Any suggestion?

Many thanks.

Christian


I have added the asp.net and the c# code behind file below.


<%@ Page language="c#" Codebehind="variable_proposal_form.aspx.cs" AutoEventWireup="false" Inherits="geoconda.MembersOnly.variable_proposal_form" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
      <HEAD>
            <title>variable_proposal_form</title>
            <meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
            <meta name="CODE_LANGUAGE" Content="C#">
            <meta name="vs_defaultClientScript" content="JavaScript">
            <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
      </HEAD>
      <body MS_POSITIONING="GridLayout">
            <form id="variable_proposal_form" method="post" runat="server">
                  <asp:textbox id="cat_value" style="Z-INDEX: 101; LEFT: 312px; POSITION: absolute; TOP: 152px"
                        runat="server"></asp:textbox>
                  <asp:DataGrid id="categories_datagrid" runat="server" style="Z-INDEX: 102; LEFT: 40px; POSITION: absolute; TOP: 136px"></asp:DataGrid>
                  <asp:textbox id="cat_value_label" runat="server" style="Z-INDEX: 103; LEFT: 320px; POSITION: absolute; TOP: 288px"></asp:textbox>
                  <asp:label id="value" runat="server" Font-Bold="True" style="Z-INDEX: 104; LEFT: 336px; POSITION: absolute; TOP: 120px">Value:
                  </asp:label>
                  <asp:label id="value_label" runat="server" Font-Bold="True" style="Z-INDEX: 105; LEFT: 352px; POSITION: absolute; TOP: 232px">Value Label:
                  </asp:label>
                  <asp:button id="add_category" runat="server" Text="<" style="Z-INDEX: 106; LEFT: 264px; POSITION: absolute; TOP: 168px"></asp:button>
                  <asp:button id="remove_category" runat="server" Text=">" style="Z-INDEX: 107; LEFT: 272px; POSITION: absolute; TOP: 232px"></asp:button>
            </form>
      </body>
</HTML>


code behind file:

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

namespace geoconda.MembersOnly
{
      /// <summary>
      /// Summary description for variable_proposal_form.
      /// </summary>
      public class variable_proposal_form : System.Web.UI.Page
      {
            protected System.Web.UI.WebControls.TextBox cat_value;
            protected System.Web.UI.WebControls.DataGrid categories_datagrid;
            protected System.Web.UI.WebControls.TextBox cat_value_label;
            protected System.Web.UI.WebControls.Label value;
            protected System.Web.UI.WebControls.Label value_label;
            protected System.Web.UI.WebControls.Button add_category;
            protected System.Web.UI.WebControls.Button remove_category;
            protected DataSet dataSet;
      
            private void Page_Load(object sender, System.EventArgs e)
            {
                  // Put user code to initialize the page here
                  if (!IsPostBack)
                  {
                        BindGrid();
                  }
            }

            #region Web Form Designer generated code
            override protected void OnInit(EventArgs e)
            {
                  //
                  // CODEGEN: This call is required by the ASP.NET Web Form Designer.
                  //
                  InitializeComponent();
                  base.OnInit(e);
            }
            
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
            {    
                  this.categories_datagrid.SelectedIndexChanged += new System.EventHandler(this.categories_datagrid_SelectedIndexChanged);
                  this.add_category.Click += new System.EventHandler(this.add_category_Click);
                  this.remove_category.Click += new System.EventHandler(this.remove_category_Click);
                  this.Load += new System.EventHandler(this.Page_Load);

            }
            #endregion

            private void BindGrid()
            {
                  dataSet = new DataSet();

                  DataTable categories = new DataTable( "categories" );
                  categories.Columns.Add( new DataColumn( "value", typeof(string) ) );
                  categories.Columns.Add( new DataColumn( "value_label", typeof(string) ) );
                  dataSet.Tables.Add( categories );

                  categories_datagrid.DataSource = dataSet.Tables[ "categories" ];
                  categories_datagrid.DataBind();
            }

            private void categories_datagrid_SelectedIndexChanged(object sender, System.EventArgs e)
            {
            
            }

            private void add_category_Click(object sender, System.EventArgs e)
            {
                  DataRow newRow;

                  dataSet.Tables[ "categories" ].NewRow();
                  newRow = dataSet.Tables[ "categories" ].NewRow();
                  newRow["value"] = cat_value.Text;
                  newRow["value_label"] = cat_value_label.Text;
                  dataSet.Tables[ "categories" ].Rows.Add( newRow );
                  
                  categories_datagrid.DataBind();

                  cat_value.Text = "";
                  cat_value_label.Text = "";
            }

            private void remove_category_Click(object sender, System.EventArgs e)
            {
            
            }
      }
}

0
Comment
Question by:csetzkorn
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
3 Comments
 
LVL 3

Expert Comment

by:skpatra
ID: 12285957
Let me first explain the problem and then offer solutions and work arounds: ASP.Net code behind SIMULATES an object model for the page to be viewed. This is how it works:
1. ser makes a request to a.aspx
2. The class for a.aspx is instantiated.
3. All the event handlers are called (including Page_Load(). This is where your dataset is populated.
4. All ASP.Net controls write the viewstate to a state property bag. This is rendered to the page as encrypted string. (that is whay you see a hidden field named __VIEWSTATE in any aspx page source)
4. ASP.Net calls render methods on the page controls to extract the HTML (I will skip some detailed steps here).
5. Class is then DESTROYED and HTML is rendered.
6. There is a post back.
7. ASP.Net instantiates the class for a.aspx for the SECOND time. (Hence your dataset value will be null here).
8. All controls read values from the viewstate.
9. All control events are called (i.e. Page_Load)
10. The processing continues as before.

So in this cycle, the code behind class actually gets instantiated number of times (= 1 + number of post backs). Now, controls save their properties in the viewstate and retrieve it in the subsequent call. (Datasource property of the datagrid control does not get saved in the viewstate by default).
So to get around your problem you have a number of options:
1. Save the dataset in session (problem is, the web server will be overloaded)
2. Save the dataset in the viewstate (page wil be very heavy). You can use the code
    ViewState.Add("somename", dataSet)
in the BindGrid. Then modify your page load as
     private void Page_Load(object sender, System.EventArgs e)
          {
               // Put user code to initialize the page here
               if (!IsPostBack)
               {
                    BindGrid();
               }
               else
               {
                    dataSet = (DataSet)(ViewState["somename"]);
          }
3. Iterate through the datagrid object item collection to get all data. Form a dataset from these data. Add a row manually to the dataset created. Then bind this dataset. This requires some coding. But it should provide good performance and less load on the server (and the page size will not go up!).

0
 

Author Comment

by:csetzkorn
ID: 12286350
Thanks for your reply.

Where would I have to add the line:

ViewState.Add("somename", dataSet)
 
Could you please elaborate point three a bit more?

Thanks!
0
 
LVL 3

Accepted Solution

by:
skpatra earned 1000 total points
ID: 12286567
if (!IsPostBack)
               {
                    BindGrid();
                    ViewState.Add("somename", dataSet)
               }

POINT 3:
----------------
Here, on Postback, you will need to recreate the dataset and then add rows for the existing values in the datagrid. You may change the code for the page_load event handler as follows.
---------------------------------
 if (!IsPostBack)
{
    BindGrid();
    ViewState.Add("somename", dataSet)
}
else
{
    //1. create the dataset structure again
    dataSet = new DataSet();
    DataTable categories = new DataTable( "categories" );
    categories.Columns.Add( new DataColumn( "value", typeof(string) ) );
    categories.Columns.Add( new DataColumn( "value_label", typeof(string) ) );
    dataSet.Tables.Add( categories );

    //2. Read existing data from grid
    foreach(DataGridItem oItem in categories_datagrid.Items)
    {
        string sVal = oItem.Cells[0].Text;
        string sValLabel = oItem.Cells[1].Text;
        categories.Rows.Add(new object[]{sVal, sValLabel});
    }
-----------------------
Note that on post back we are just creating the dataset structure again. Then we are looping through the datagrid items to read the existing values and for each row, we add a tablerow to the datatable. This is happening in Page_Load which is called before the add click. The add click just appends one extra row to the daatable and then re-binds the grid.

}
0

Featured Post

NFR key for Veeam Backup for Microsoft Office 365

Veeam is happy to provide a free NFR license (for 1 year, up to 10 users). This license allows for the non‑production use of Veeam Backup for Microsoft Office 365 in your home lab without any feature limitations.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Wouldn’t it be nice if you could test whether an element is contained in an array by using a Contains method just like the one available on List objects? Wouldn’t it be good if you could write code like this? (CODE) In .NET 3.5, this is possible…
A long time ago (May 2011), I have written an article showing you how to create a DLL using Visual Studio 2005 to be hosted in SQL Server 2005. That was valid at that time and it is still valid if you are still using these versions. You can still re…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
Have you created a query with information for a calendar? ... and then, abra-cadabra, the calendar is done?! I am going to show you how to make that happen. Visualize your data!  ... really see it To use the code to create a calendar from a q…

610 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question