I have a ListBox which I am adding ListItems to in a codebehind. The problem I'm having is the ListBox is not seeing the selected items. I have the ListBox being populated dynamically depending on what the user selects from a DropDownList, so the DropDownList has AutoPostBack set to true. I think this is somehow causing the problem.
My SelectedIndexChanged method, which is used whenever an item in the DropDownList is selected, calls a method called PopulateListBox. Here's what those methods looks like:
protected void SelectedIndexChanged(object sender, EventArgs e)
{
string typeStr = type.SelectedItem.Text;
MyType = Api.GetType(typeStr);
PopulateListBox();
}
private void PopulateListBox()
{
listbox.Items.Clear();
foreach (PropertyInfo info in MyType.GetProperties())
listbox.Items.Add(new ListItem(info.Name));
}
For what it's worth, here are the DropDownList and ListBox:
<asp:DropDownList runat="server" ID="type" width="281px" OnSelectedIndexChanged="SelectedIndexChanged" AutoPostBack="true" />
<asp:ListBox runat="server" ID="listbox" width="281px" height="200px" selectionmode="Multiple" />
What I am trying to do is add a List of strings (strings being the selected items) as a session variable upon clicking a submit button. The button redirects to a new page after the List has been added to the session. Going through in debugger, the List of strings is empty at the point where I add it to the session.
listbox.GetSelectedIndices() returns nothing.
Update
I can access the selected items if I do not make a change in the DropDownList. The ListBox is initially populated on page load, and if I make selections they are recognized. If I select something from the DropDownList and the ListBox is repopulated, the selections are not recognized.
My Page_Load method does only two things. It initializes my Api variable and calls PopulateDropDown, which looks like this:
private void PopulateDropDown()
{
foreach (Type t in Api.GetAllTypes())
type.Items.Add(new ListItem(t.Name));
string typeStr = type.Items[0].Text;
Type = Api.GetType(typeStr);
PopulateListBox();
}
The problem is that you call PopulateDropDown() on every single Page_Load(), which calls PopulateListBox(), which clears the listbox and repopulates it. By clearing the listbox, you clear the selection.
You need to replace your call to PopulateDropDown() in the Page_Load() with the following code. The issue that I think you don't realize is that the page is loaded on every postback -- and that in the page life cycle, the page load occurs before the event. So by selecting a drop down item, you execute the Page_Load() event first (which indirectly executes the LoadListBox method, clearing the selection). The following code will populate the drop down list the first time the page loads only. Keep it the same wherever else you are using the load dropdown method:
protected void Page_Load(object sender, EventArgs e)
{
// Do your API code here unless you want it to occur only the first
// time the page loads, in which case put it in the IF statement below.
if (!IsPostBack)
{
PopulateDropDown();
}
}
The IsPostBack returns a boolean indicating whether the server side code is running because the page is loading for the first time ("false") or as a post back ("true").
As I said elsewhere, keep in mind that a listbox with potential for multiple selected values must be handled differently than one with potential for a single selection. Don't reference listbox.SelectedItem, but rather:
foreach (ListItem item in lbFullNames)
{
if (item.Selected)
{
// TODO: Whatever you are doing with a selected item.
}
}
I have also found that if you disable the ListBox server-side, then use client side code to enable the list box using code like the following, then you cannot get the selected items server side.
$('.css-class-assigned-to-listbox').attr('disabled', '');
The fix is simply to make sure it is enabled server-side (the default), then disable it (see blow) or enable it (see above) using client-side code.
$('.css-class-assigned-to-listbox').attr('disabled', 'disabled');
Related
My aspx file where the DDL is defined:
<asp:DropDownList ID="myDDL" runat="server"
OnSelectedIndexChanged="myDdlChange"
AutoPostBack="true" EnableViewState="true" />
My code behind file
protected void PopulateControl()
{
//populate my DDL based on an array (OK)
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
PopulateControl();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
...
this.DataBind();
}
protected void myDdlChange(object source, EventArgs e)
{
Session["myDDL"] = myDDL.SelectedValue;
myTextBox.Text = MyMethod(myDDL.SelectedValue);
}
myTextBox is a text box which is populated every time the DDL changes based through a method that takes the selected value as parameter.
What more needs to be added for the DDL to keep the user's selected value.
Right now, when I switch to another value in the DDL, my selected value is switched back to the first element of the array.
Also, why doesn't myDdlChange method take focus when I debug and switch to another value in the DDL? (I've a breakpoint inside this method)
Because every time you do this:
PopulateControl();
You remove all of the values in the DropDownList and re-add them. So whatever the user selected was removed, and a fresh list of (unselected) values was added. This happens every time the page loads, which takes place before the myDdlChange handler.
You can prevent this from re-populating the list on post-backs:
if (!IsPostBack)
PopulateControl();
That way the DropDownList is populated only on an initial page load and not on subsequent post-back page loads.
Also, why doesn't myDdlChange method take focus when I debug and switch to another value in the DDL?
Are you posting back to the server when you switch to another value? If not then nothing is invoking server-side code. If you are posting back to the server, have you registered this event with the control? The designer normally does this for you, but if you created this manually then you'd need to register it with the control manually as well.
I have a dropdown list which is populated on page_load using a linq query.
If I change the value in the dropdown then click a button to run an update query on the record, the original value is still there, if I step through in debug mode I can see the selected value is not changing at all
Here is how Im binding the data to dropdown
dlBookingRef.DataSource = d.BookingRef();
dlBookingRef.DataMember = "booking";
dlBookingRef.DataBind();
and here is the line in the function which gets the data from the form
item.booking_ref = dlBookingRef.SelectedValue;
Any idea why it's retaining its original value?
thanks
Put the binding code in if(!IsPostBack), it looks like that in button event as page load gets called due to that your dropdown list gets reset, so bind the dropdown only when page is not posted back:
protected void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostBack)
{
dlBookingRef.DataSource = d.BookingRef();
dlBookingRef.DataMember = "booking";
dlBookingRef.DataBind();
}
}
Here is my button click code:
protected void ImageButton_Run_Click(object sender, ImageClickEventArgs e)
{
if (selectedFilter == "AgentID")
{
List<string> selectedValues = CheckBoxList_Options.Items.Cast<ListItem>().Where(li => li.Selected).Select(li => li.Value).ToList();
var selectedItems = CheckBoxList_Options.Items.Cast<ListItem>().Where(x => x.Selected);
}
Response.Redirect("AgentSkillMapReport.aspx");
}
Selected values are always empty even if I have selected checkboxs in chckboxlist. I think values are cleared on postback. How to retain its values. Help me out friends. Thanks in advance :)
You could use session variable
session["checkBox_selectedItems"]= CheckBoxList_Options.Items.Cast().Where(x => x.Selected);
keep in mind, that memory is a limited resource, and it depends on the number of connections at a given time. So, these kind of variables are used to store small amount of data... They are an object, wich means that can store everything you want
I have binded the data source for checkbox in my button click method. So every time i click the button it gets refreshed on postback and i am losing the selected values in my checkboxlist. I have moved my code to page_load event and i wrapped the code unded if(!ispostback) and everything works fine now. My selections are retained after button click.
I have a page with a repeater in it. I'm writing an event handler so that when the user clicks my WebControl button, the event handler for said button iterates through the items in the repeater using FindControl, then uses some of the controls' values. It seems though, that after the page is loaded, the repeater items populate, but when the button is clicked to post this back, as I iterate through the repeater items, I'm seeing that they're all empty. I don't completely understand the sequencing, but I'm assuming it's because my iteration code is trying to access RepeaterItems that haven't been set yet.
The repeater code is in my OnLoad method. Outside of that, I have my event handler trying to iterate through those items after being clicked. This is essentially what I was trying to do:
protected void MyButton_Click(object sender, EventArgs e)
{
foreach(RepeaterItem item in MyRepeater.Items)
{
MyLabel = (Label)item.FindControl("MyLabel");
}
}
The button is located in the FooterTemplate of the repeater.
<asp:Button runat="server" OnClick="SubmitChecklist_Click" cssclass="BlueSubmit" id="SubmitChecklist" text="Submit" />
Thanks in advance.
Edit: To clarify, the exact error I'm getting is NullReferenceException, when I try to do something, for instance, Response.Write(MyLabel.Text)
Edit: After looking into it more today, this is what I understand to be happening: The repeater is databound on postback. When I then make selections from the generated dropdownlists and hit my button, it posts back again. At this point, the repeater is databound again to it's initial values. So, if I must postback in order to get the users' selections, how can I go about this in the button's eventhandler so that I can get the selected values before that repeater gets databound again?
THe problem, it sounds like, is that you may be binding the data to your repeater on load, but not first checking to make sure it isnt a post back.
example:
You request the page. On Load Fires. You bind the data to the repeater.
You maniupulate the data in the reapter then click your button
The page refreshes with the postback, firing the onload event. The data is rebound to your repeater and all previous data entered has been nullified.
the onclick event is triggered and your code tries to retrieve values that no longer exist.
Make sure your databinding code in your onLoad event is nested within an postback check
if (!Page.IsPostBack)
{
Repeater.DataSource = Datatable;
Repeater.DataBind();
}
I've seen the same thing. I don't understand why, but the data doesn't actually get bound until after all events have fired. I ended up making my data source available at the class level and then indexing.
private DataTable myTable;
protected void Page_Load(object sender, EventArgs e)
{
//populate dataTable
if (!IsPostBack)
{
//databind to repeater
}
}
protected void Submit_Click(object sender, EventArgs e)
{
foreach (RepeaterItem item in repeater1.Items)
{
DataRow row = myTable.Rows[item.ItemIndex];
}
}
Ideal? Certainly not but it works.
Instead of relying on the IsPostBack in my OnLoad, I just seperated all of the different states by putting the databinding of the repeater inside of an event handler after the user selects the first option, rather than relying on the IsPostBack of OnLoad. It was a bit convoluted, but I think I'm doing it the right way this time.
Basically, I have a drop down list and a dynamically added user control. The user control loads a grid view depending on the choice that was made in the drop down list. The drop down list is not part of the user control.
Now, the question is, how do i simulate (isControlPostback = false) every time the user changes the selection in the drop down list? It looks like ViewState remembers the control.
Inside my user control I have:
protected bool IsUserControlPostBack
{
get
{
return this.ViewState["IsUserControlPostBack"] != null;
}
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsUserControlPostBack)
{
ViewState.Add("IsUserControlPostBack", true);
//load stuff in the grid view and bind it
}
}
When the user changes the selection on the drop down list, i have a javascript confirm box, and the page posts back. So OnSelectedIndexChanged event for drop down list doesn't get triggered. I would like to remove to do something like this every time the selected index changes:
ViewState.Remove("IsUserControlPostBack");
You can make changes to the control in prerender event. When this event is fired all other actions are made.
Or you can do public property in user control and when setting required to value react on appropriately.
The ViewState you access in your user control is not the same one you access on the page. If you need your page to communicate with your user control, I suggest you add a public method on your user control for this purpose.
If, for some reason, you prefer
something similar to your ViewState
approach, you can try Context.Items.
Note that Context.Items is not
preserved between requests.
Add the control to the page sometime before OnLoad. E.g. OnInit. Between OnInit and OnLoad, the viewstate is loaded and postback events are run.
For anyone who is interested to know the answer:
I ended up implementing a public property inside user control and load the control inside the server drop down list SelectedIndexChanged event rather than OnInit. This eliminated the need for explicit Viewstate use.