In my ASP.NET page, I have a generic class that is defined as below:
public partial class log_states : BasePage
{
protected class StatesUsed
{
public int StateCode { get; set; }
public string StateName { get; set; }
}
private List<StatesUsed> _statesUsed;
}
In the Page_Load() event, I initialize _statesUsed like below, and bind it to a grid:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
_statesUsed = new List<StatesUsed>();
BindMyGrid();
}
}
private void BindMyGrid()
{
gvStates.DataSource = _statesUsed;
gvStates.DataBind();
}
I then have a form to add new States. When the user adds a state, I'm trying to add it to the local _statesUsed variable, and rebind the grid. Example:
protected void btnAddState_Click(object sender, EventArgs e)
{
_statesUsed.Add(new StatesUsed { StateCode = 1, StateName = "Test" });
BindMyGrid();
}
This always fails when trying to add the new item saying "Object reference not set to an instance of an object"...
How do I keep _statesUsed persistant? The idea is to add all user input using the generic class and then update the database at one go. If you know of another way to accomplish this, I'd be very grateful.
Thanks in advance!
Instead of
private List<StatesUsed> _statesUsed;
I'm usually using something similar to:
private List<StatesUsed> _statesUsed
{
get
{
var result = ViewState["_stateUsed"] as List<StatesUsed>;
if ( result == null )
{
result = new List<StatesUsed>();
ViewState["_stateUsed"] = result;
}
return result;
}
}
I.e. I am persisting page class variables to the ViewState.
If you want to keep stuff "alive" through multiple postbacks you either have to store stuff to a database, use Session, use the Viewstate, or store it temporarily in shared server memory. Which of these you choose is dependent on your use case,
In your case I would probably add an asp:HiddenField runat="server" ID="HiddenFieldUsedStateIDs" in which I wrote the IDs comma separated whenever there is a change and then read the values into the generic list in Page_Load (on every Page_Load, not just !IsPostBack)
This would utilize the Viewstate mechanism in Asp.Net to write the values to the rendered HTML and read it back into the HiddenField's value on each post
Asuuming that your viewstate in not disabled, you could do,
protected void btnAddMat_Click(object sender, EventArgs e)
{
List<StatesUsed> temp = null;
temp = (List<StatesUsed>)gvStates.DataSource;
if(temp != null)
temp.Add(new StatesUsed { StateCode = 1, StateName = "Test" });
gvStates.DataBind();
}
Related
I have a subclassed Button with a couple of properties
public class ZButton : Button
{
private string UIB = "I";
public int _id_ { get; set; }
public int rowIndex { get; set; }
protected override void OnClick(EventArgs e)
{
Form frmNew = new Form(UIB);
frmNew.ShowDialog();
base.OnClick(e);
}
}
I placed that button on the form and here is the code for that button in the form.
private void zButton1_Click(object sender, EventArgs e)
{
rowIndex = dataGridView1.CurrentRow.Index;
_id_ = Convert.ToInt16( dataGridView1["id_city", rowIndex].Value.ToString());
}
I cant access those properties (rowIndex) and (id) and compiler gives errors
The name 'rowIndex' does not exist in the current context
I am rather new to C# so I must be missing something obviuos.
rowIndex and _id_ are properties of your zButton, they are not accesible directly in your form. So if you need to access them in the click event, you have to cast the sender to a zButton and access the properties of that instance.Something like this:
private void zButton1_Click(object sender, EventArgs e)
{
zButton but=(zButton)sender;
but.rowIndex = dataGridView1.CurrentRow.Index;
but._id_ = Convert.ToInt16(dataGridView1["id_city",but.rowIndex].Value.ToString());
}
If method zButton1_Click is a member of your form class, then it can directly access properties of the same class or its ancestor classes, not properties of aggregated objects like your button.
In order to access your button's properties, you should explicitly specify which object's properties you are trying to access. This means that if you want to access a property of an aggregated button zButton1, you should replace
dataGridView1["id_city", rowIndex]
with
dataGridView1["id_city", zButton1.rowIndex]
cast your sender to button.
var button = sender as zButton;
if (button != null)
{
button.rowIndex ...
...
}
I am trying to populate a listview each time a button is selected. At the moment I have the button populating the listview once each time. Each time a new value is entered it will overwrite the current listview.
I want to be able to add in a new item and continue till there is multiple rows.
protected void btnAddSkuBarcode_Click(object sender, EventArgs e)
{
var SKUS = new List<SkuBar>
{
new SkuBar {SkuBarcode = txtSkuBarcode.Text , Qty = txtQty.Text},
};
lvWebLabels.DataSource = SKUS;
lvWebLabels.DataBind();
}
public class SkuBar
{
public string SkuBarcode { get; set; }
public string Qty { get; set; }
}
Currently you're creating a new variable (SKUS) every time the button is clicked. When you bind to that new list, you lose anything previously bound to the control.
Since the list needs to persist in a greater scope than just the method, put it in something like class scope:
List<SkuBar> SKUS = new List<SkuBar>();
Then just add to the existing list:
protected void btnAddSkuBarcode_Click(object sender, EventArgs e)
{
SKUS.Add(new SkuBar {SkuBarcode = txtSkuBarcode.Text , Qty = txtQty.Text});
lvWebLabels.DataSource = SKUS;
lvWebLabels.DataBind();
}
Note that this will only work in a stateful system. If by chance you're using WebForms then the object itself is also dropped from scope for each request, so you'd need to persist the data somewhere else. Session state, database, etc.
You're creating a new List<T> every time the button is clicked so you lose the previous one. Define the List<T> outside of the button press so it can be re-used:
namespace YourNamespace
{
public class YourClass
{
List<SkuBar> SKUS;
public YourClass() // Or form load or whatever
{
SKUS = new List<SkuBar>();
}
protected void btnAddSkuBarcode_Click(object sender, EventArgs e)
{
SKUS.Add(new SkuBar {SkuBarcode = txtSkuBarcode.Text , Qty = txtQty.Text});
lvWebLabels.DataSource = SKUS;
lvWebLabels.DataBind();
}
}
}
Is there any way I can reference a GridView object as a variable within my code behind page so I can refer to it once rather than multiple times?
I'm trying to make my code easier for me to update, and easier to transport. The less references I have to use the better!
This is an example of how my code sort of looks at the moment, there must be a better way of declaring the var GridView_ variable outside of the scope of each void?
public class GlobalVars
{
// Button Toggle
public static bool boolToggleView = false;
// Column Indexes
public static int Column1Index = new int();
}
protected void GetColumnIndexes()
{
// GridView Variable
var GridView_ = GridViewName;
// Column Indexes
GlobalVars.Column1Index = Utility.GetColumnIndexByName(GridView_, "Column1");
}
protected void Button1_Click(object sender, EventArgs e)
{
// GridView Variable
var GridView_ = GridViewName;
if (GlobalVars.boolToggleView)
{
GlobalVars.boolToggleView = false;
}
else
{
GlobalVars.boolToggleView = true;
}
// Bind GridView
GridView_.DataBind();
}
This is probably the biggest noob question ever but I'm confused as to why my private variables, when they are set in one method, gets reset in another. I have something like this in my code:
namespace Project.Messages
{
public partial class Inbox : System.Web.UI.Page
{
private static int selectedIndex;
private static string messageIDString;
private static int messageID;
//select message to view
protected void viewMessage(object sender, GridViewCommandEventArgs e)
{
//get index
selectedIndex = MsgInbox.SelectedIndex;
if (int.TryParse(e.CommandArgument.ToString(), out selectedIndex))
{
//get selected dataKey, convert to a int
messageIDString = MsgInbox.DataKeys[selectedIndex].Value.ToString();
messageID = Convert.ToInt16(messageIDString);
}
}
//select message to delete
protected void delBTN_Click(object sender, EventArgs e)
{
SqlCommand com = new SqlCommand("DELETE FROM Messages WHERE MessageID = #param1", conn);
conn.Open();
com.Parameters.AddWithValue("param1", messageID);
}
So if I click a message, messageID will be set and the message will be displayed. When I click to delete message after that though, it looks like the variable is resetting/is not the same value as previously set. Do I need to use a static variable or something to achieve this?
Thanks
That is the behaviour. When there is postback, all variables are reset and reassigned. You can use session or viewstate or store the value in a control on the page which is already part of the viewstate e.g. in an hidden field
public int messageID
{
get
{
int retVal = 0;
if(ViewState["messageID"] != null)
Int32.TryParse(ViewState["messageID"].ToString(), out retVal);
return retVal;
}
set { ViewState["messageID"] = value; }
}
It's because of ASP.NET, not C#. You need to save your variables in viewstate. See: variable initialized in class loses its previous value with the page loading
It is because the web is stateless. Here are some methods for passing data between pages.
ASP.net MVC:
http://msdn.microsoft.com/en-us/library/dd394711(v=vs.100).aspx
ASP.net Webforms
http://msdn.microsoft.com/en-us/library/6c3yckfw(v=VS.100).aspx
Hope this helps.
You can also use Session object to store information that you need between requests.
Eg: Session["messageIdString"]=value
For more info : http://msdn.microsoft.com/en-us/library/ms178581(v=vs.100).aspx
Can I assign a value to a variable (int) and never lose this value inside any scope ?
the problem is I am assigning the value to the variable in some scopes but the variable returns to its default value (zero) in other scopes..
Example :
protected void Button_AddNewCourse_Click(object sender, EventArgs e)
{
ID = 10;
}
so when I am trying to use ID in other functions it falls back to zero
protected void AnotherFunction(object sender, EventArgs e)
{
// Variable ID here is zero
}
At a guess, perhaps you're a newcomer to ASP.NET and haven't figured out why page-level variables don't keep their state between postbacks. Try reading up on Session state and Viewstate
Or for a general overview: ASP.NET State Management Overview
e.g. based on your code example, you could use a Session entry to store the value:
protected void Button_AddNewCourse_Click(object sender, EventArgs e)
{
Session["ID"] = 10;
}
protected void AnotherFunction(object sender, EventArgs e)
{
int tempID = (int)Session["ID"];
}
There's lots of other things you could also do - use Viewstate, for example.
Change the line that looks similar to this (which is probably somewhere):
public int ID { get; set;}
to something like
// keep the value of ID in this page only
public int ID { get { return (int)ViewState["ID"]; } set { ViewState["ID"] = value; } }
or
// keep the value of ID in every page
public int ID { get { return (int)Session["ID"]; } set { Session["ID"] = value; } }
Maybe try using readonly variables?