I'm making a web app in Asp.Net using c# that lets you add items into the list.
My problem is that each time that i click the button to add a new item into the list , its just shows me the last item and the list counter shows me only 1 .
What am I doing wrong??
Here is the code :
public partial class home : System.Web.UI.Page
{
List<string> messageboxs = new List<string>();
public string val = "";
public string data = "";
protected void Button1_Click(object sender, EventArgs e)
{
val = "";
messageboxs.Add(text1.Text);
ListBox1.DataSource = messageboxs;
ListBox1.DataBind();
val = messageboxs.Count.ToString();
}
}
Your list is not persisted between postbacks.
Every time you click a button a new instance of the page class and therefore list is created. This list is empty.
You should read up on ASP.NET Page Life Cycle Overview. In a nut shell, everytime you click the button it causes the page to postback which creates a new instance of the page. You are initializing an empty list on each instance of that page therefore when you come to adding the new item into the list...it's empty again.
What you need to do is store messageboxs somewhere which will allow it to persist across postbacks. For your particular example, you could use the ViewState e.g.
public partial class home : System.Web.UI.Page
{
private void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
// initialise list
ViewState["Messages"] = new List<string>();
}
}
protected void Button1_Click(object sender, EventArgs e)
{
// get the old messages list
var messages = (List<string>)ViewState["Messages"];
messages.Add(text1.Text);
ListBox1.DataSource = messages;
ListBox1.DataBind();
// store the new messages list
ViewState["Messages"] = messages;
}
}
The problem is in how ASP.Net works. ASP.Net is recreating your "home" page on each button click. This then recreates the list, and you add one item to it. You need a way to save the list between button clicks. That's what, for example, the Session is for.
The list is created again on each postback. You should look at going through the existing items in ListBox1 and re-adding them to your List<string> then re-binding.
Make your messageboxs static variable as
static List messageboxs = new List();
But this makes the variable accessible from any page request.
meaning if someone else open this page and tried to add an item he/she will end up adding an item to someone else's list.
try using session state or view state instead.
Related
I have a webpage: Menu.aspx, where I have the following controls of relevance:
a DropDownList with some values
a button, which redirects me to a page called Edit.aspx.
In my Edit.aspx page, I have a cancel button, which redirects the user back to the Menu page with the following C# method
protected void btnCancel_click(object sender, EventArgs e)
{
Response.Redirect("Menu.aspx");
}
What I would like to do is when I redirect my user back to Menu.aspx, I preserve the value of the DropDownList that they selected.
Thanks in advance!
EDIT: Ideally, I want to achieve this without a QueryString (if Possible)
EDIT2: I was thinking of something invovling a viewstate or postback but I'm unfamiliar with those.
When you called Response.Redirect("Menu.aspx"); you were already making a new request which the previous page was not part. It's like calling the page anew.
You can put the value in session before coming to Edit.aspx or pass the value back through query string
Response.Redirect("Menu.aspx?dropdownvalue=123");
On Menu.aspx, you'll check if ?dropdownvalue=123 exist and you set selected item to that value
Isn't the most ellegant solution, but you can create a session variable containing the selected value.
For example:
dropDown_SelectedIndex(object sender, EventArgs e)
{
Session["SelectedItem"] = dropDown.SelectedValue;
}
When you do the redirect, on the page load of the Menu.aspx, after you populate the DropDown, check if this session variable exists, then select the item and remove it from the application.
void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
//populate drop down here
if(Session["SelectedItem"] != null)
{
dropDown.SelectedValue = Session["SelectedItem"].ToString();
Session["SelectedItem"] = null;
}
}
}
Or you can pass it via query string, but this way you preserve you url
This is the code:
private void button1_Click(object sender, EventArgs e)
{
List<string> user = new List<string>();
user.Add(usertextBox.Text);
I want it where each time I press the button, whatever is in usertextBox at that point gets added to the list 'user' as a new item, so I can recall the different ones later with [1], [2], [3], etc. I also want it so the user can close the app and all the users will still be saved. I I don't know if C# does this automatically
Even if you can only answer one of my questions that's fine. Thanks!!
In your code you are making List local to Button that means every time you click button new object of List is created, You should create it out side button click method. Try this.
List<string> user = new List<string>();
private void button1_Click(object sender, EventArgs e)
{
user.Add(usertextBox.Text);
You have to define the List out side of the method. C# does not keep the content of the list.
private List<string> user = new List<string>();
private void button1_Click(object sender, EventArgs e)
{
user.Add(usertextBox.Text);
}
for saving the content you could use a database (http://msdn.microsoft.com/en-us/library/bb655884%28v=vs.90%29.aspx) or an xml file (http://www.codeproject.com/Articles/7718/Using-XML-in-C-in-the-simplest-way).
to save the content of the List you could create a new class containing this two methods instead of the list
public List<string> getListContent()
{
//read xml-file
}
public void Add(string t)
{
//write to xml file
}
This will just fine work in single thread applications.
I want to get some data to fill a listview control, but this data it's determined in other form. This is what I code in form1 (Nuevo_Credito):
private void combo_cliente_SelectionChangeCommitted(object sender, EventArgs e)
{
Credito_Grupo ventana = new Credito_Grupo(combo_cliente.SelectedItem);
ventana.ShowDialog();
}
public void AgregaIntegrantes(string id, string nombre, string monto)
{
ListViewItem elem = new ListViewItem(id);
elem.SubItems.Add(nombre);
elem.SubItems.Add(monto);
listView_integrantes.Items.Add(elem);
}
I'm invoking form2 (Credito_grupo) as show dialog window, then I want to retrieve some values and pass them to Form1 using the public method "AgregaIntegrantes". So in form2 I did the following:
public Credito_Grupo(dynamic item)
{
this.id = item.IDCliente;
this.nombre = item.NomComp;
InitializeComponent();
}
private void Credito_Grupo_Load(object sender, EventArgs e)
{
text_nombre.Text = this.nombre;
}
private void button_AgregaCliente_Click(object sender, EventArgs e)
{
Nuevo_Credito obj = new Nuevo_Credito();
obj.AgregaIntegrantes(id.ToString(), nombre, text_monto.Text);
this.Close();
}
When the event button_AgregaCliente_click is triggered I need to add the data to listview in form1 using the method described above, but none data is added. I found a solution using delegates here 3077677, is there an approach using objects?
You have an error in button_AgregaCliente_Click method (the last one in the listing). You create a new Nuevo_Credito form there, and pass the data to listview. It looks OK. But this newly created Nuevo_Credito form does exist only in the local variable, so then you throw it away without displaying it when button_AgregaCliente_Click finishes.
I think you need to delete this line: Nuevo_Credito obj = new Nuevo_Credito();
You need to get your real Nuevo_Credito form, not create a new one here.
You can send this from your Nuevo_Credito to the constructor of the Credito_Grupo form. Then you can use it to call back to the original Nuevo_Credito. This approach is based only on objects, and not delegates. As you wanted. :-)
I want to reload the combo box so that it would display the values recently entered by me.
The Language used is C#.Net 2005..I am making a windows application. Please guide me?
you just need to call the method .DataBind() every time you want to "refresh" the combobox with new data
Save your last entered values, then load them when the comboBox is loaded. Something like:
private stirng _comboBoxSavedListPath = "";//or from application settings..
private List<string> _comboBoxLastEnteredValues = new List<string>();
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)//or whenever you want to save
{
if (comboBox1.SelectedIndex > -1)
{
string entry = comboBox1.SelectedItem.ToString();
if (!_comboBoxLastEnteredValues.Contains(entry))
{
_comboBoxLastEnteredValues.Add(entry);
}
}
}
Now handle the form Closing event or just save the list again whenever item added. and load the list whenever form is loaded:
private void form1_Closing..
{
SaveList(_comboBoxLastEnteredValues);//Like(File.WriteAllLines(_comboBoxLastEnteredValues.ToArray(), _comboBoxSavedListPath);
}
private void form1_Load...
{
_comboBoxLastEnteredValues = LoadLastSavedList();//Like File.ReadAllLines(_comboBoxSavedListPath);
}
I need to generate buttons initially based on quite a processor and disk intensive search. Each button will represent a selection and trigger a postback. My issue is that the postback does not trigger the command b_Command. I guess because the original buttons have not been re-created. I cannot affort to execute the original search in the postback to re-create the buttons so I would like to generate the required button from the postback info.
How and where shoud I be doing this? Should I be doing it before Page_Load for example? How can I re-construct the CommandEventHandler from the postback - if at all?
namespace CloudNavigation
{
public partial class Test : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
// how can I re-generate the button and hook up the event here
// without executing heavy search 1
}
else
{
// Execute heavy search 1 to generate buttons
Button b = new Button();
b.Text = "Selection 1";
b.Command += new CommandEventHandler(b_Command);
Panel1.Controls.Add(b);
}
}
void b_Command(object sender, CommandEventArgs e)
{
// Execute heavy search 2 to generate new buttons
Button b2 = new Button();
b2.Text = "Selection 2";
b2.Command += new CommandEventHandler(b_Command);
Panel1.Controls.Add(b2);
}
}
}
The b_Command Event Handler method is not being executed because on post back buttons are not being recreated (since they are dynamically generated). You need to re-create them every time your page gets recreated but in order to do this you need to explicitly cache information somewhere in state.
If this a page-scoped operation easiest way is to store it in the ViewState (as strings - if you start loading the ViewState with objects you'll see performance go down) so that you can check it on next load (or any other previous event) and re-create buttons when reloading the page.
If the operation is session-scoped, you can easily store an object (array or whatever) in session and retrieve it on next Load (or Init) to re-create your controls.
This scenario means that you need just to store some info about your button in your b_Command EventHandler instead of creating and adding buttons since if you do so you'll lose relative information in the next postback (as it is happening now).
so your code would become something like:
namespace CloudNavigation
{
public partial class Test : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
this.recreateButtons();
}
else
{
// Execute heavy search 1 to generate buttons
Button b = new Button();
b.Text = "Selection 1";
b.Command += new CommandEventHandler(b_Command);
Panel1.Controls.Add(b);
//store this stuff in ViewState for the very first time
}
}
void b_Command(object sender, CommandEventArgs e)
{
//Execute heavy search 2 to generate new buttons
//TODO: store data into ViewState or Session
//and maybe create some new buttons
}
void recreateButtons()
{
//retrieve data from ViewState or Session and create all the buttons
//wiring them up to eventHandler
}
}
}
If you don't want to call recreateButtons on page load you can do it on PreLoad or on Init events, I don't see a difference since you'll be able to access ViewState/Session variables everywhere (on Init viewstate is not applied but you can access it to re-create your dynamic buttons).
Someone will hate this solution but as far as I know the only way to retain state data server-side is ViewState - Session - Page.Transfer or client-side cookies.
The buttons need to be created before the load event, or state won't be wired up correctly. Re-create your buttons in Init() instead.
As for how to do this without re-running the search, I suggest you cache the results somewhere. The existence of a result set in the cache is how your button code in the Init() event will know it needs to run.
Alternatively, you could place the buttons on the page statically. Just put enough there to handle whatever the search returns. If you're thinking that maybe that would be way too many items, then ask your self this: will your users really want to sort through that many items? Maybe you should consider paging this data, in which case static buttons aren't as big a deal any more.
What happens when the postback event handling tries to find the control it dosen't exists on the collection.
Checkout Denis DynamicControlsPlaceholder # http://www.denisbauer.com/ASPNETControls/DynamicControlsPlaceholder.aspx
Hope it helps
Bruno Figueiredo
http://www.brunofigueiredo.com
Does your ASPX have the event handler wired up?
<asp:Button id="btnCommand" runat="server" onClick="b_Command" text="Submit" />
I agree with Joel about caching the search results. As for the buttons you can create them dynamically at the init or load phases of the page lifecycle but be aware that if you remove a button and then add it back programmatically you will mess up your state.
In one of my projects we have a dynamic form that generates field son the fly and the way we make it work is through an array that is stored in the cache or in the viewstate for the page. The array contains the buttons to display and on each page load it re-creates the buttons so that state can be loaded properly into them. Then if I need more buttons or a whole new set I flag the hide value in the array and add a new set of values in the array for the new set of corresponding buttons. This way state is not lost and the buttons continue to work.
You also need to ensure that you add a handler for the on_click event for your buttons if you create them programmatically which I think I see in your code up at the top.
Here is a sample with custom viewstate handling (note that buttons have EnableViewState = false):
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// Execute heavy search 1 to generate buttons
ButtonTexts = new ButtonState[] {
new ButtonState() { ID = "Btn1", Text = "Selection 1" }
};
}
AddButtons();
}
void b_Command(object sender, CommandEventArgs e)
{
TextBox1.Text = ((Button)sender).Text;
// Execute heavy search 2 to generate new buttons
ButtonTexts = new ButtonState[] {
new ButtonState() { ID = "Btn1", Text = "Selection 1" },
new ButtonState() { ID = "Btn2", Text = "Selection 2" }
};
AddButtons();
}
private void AddButtons()
{
Panel1.Controls.Clear();
foreach (ButtonState buttonState in this.ButtonTexts)
{
Button b = new Button();
b.EnableViewState = false;
b.ID = buttonState.ID;
b.Text = buttonState.Text;
b.Command += new CommandEventHandler(b_Command);
Panel1.Controls.Add(b);
}
}
private ButtonState[] ButtonTexts
{
get
{
ButtonState[] list = ViewState["ButtonTexts"] as ButtonState[];
if (list == null)
ButtonTexts = new ButtonState[0];
return list;
}
set { ViewState["ButtonTexts"] = value; }
}
[Serializable]
class ButtonState
{
public string ID { get; set; }
public string Text { get; set; }
}