Auto remember on DropDownList fields using Session. - asp.net

I want to implement "auto remember" feature of a form. This app is used by accountants who track cheque payments.
The accountant is entering a number of checks at a time and it will be time saving to maintain the project, beneficiary and project instead of choosing them every time you want to add a transaction.
The form looks like attached.
So far my attempts are failing and i keep seeing the dash entry '-' always at the top of each of the three dropdownfields as if i did nothing.
However 'watch' paramters shows that the Session values are properly retrieved and set.
I'm trying to save the previously entered values of those fields in a Session. Unless someone has another thought.
The nature of the fields in the asp file is as such
<asp:DropDownList ID="ddAccount" runat="server" Height="24px" OnSelectedIndexChanged="ddAccount_SelectedIndexChanged" >
<asp:ListItem>-</asp:ListItem>
</asp:DropDownList>
*<br />
<br />
<asp:DropDownList ID="ddProject" runat="server" Height="22px" >
<asp:ListItem>-</asp:ListItem>
</asp:DropDownList>
*<br />
<br />
<asp:DropDownList ID="ddBenificiary" runat="server" >
<asp:ListItem>-</asp:ListItem>
</asp:DropDownList>
*<br />
<br />
On Page_load I added the following Session getters and setters. I choose to populate first, i.e get the accounts, projects
etc then set the proper value based on the sessions.
protected void Page_Load(object sender, EventArgs e)
{
try
{
user = (User)Session["user"];
if (!IsPostBack)
{
if (Session["IsValidUser"] == null || Session["IsValidUser"].ToString() != "true")
Response.Redirect("Login.aspx", false);
/// Setting the Body tag.
Site1 m = (Site1)Master;
m.PageSection = "transactions";
//////////////////////////
Populate();
if (Session["BankAccount_ATx"] == null)
{
Session.Add("BankAccount_ATx", null);
}
else ddAccount.DataTextField = Session["BankAccount_ATx"].ToString();
if (Session["Project_ATx"] == null)
{
Session.Add("Project_ATx", null);
}
else ddProject.DataTextField = Session["Project_ATx"].ToString();
if (Session["BenefClient_ATx"] == null)
Session.Add("BenefClient_ATx", null);
else
ddBenificiary.DataTextField = Session["BenefClient_ATx"].ToString();
}
}
catch (Exception ex)
{
Response.Redirect("Login.aspx");
}
}
I save the chosen value in the session on the save button.
Session["BankAccount_ATx"] = ddAccount.SelectedValue;
Session["Project_ATx"] = ddProject.SelectedValue;
Session["BenefClient_ATx"] = ddBenificiary.SelectedValue;
Many thanks guys and gals

You want to set the selected value of the dropdownlist, like this:
if (Session["Project_ATx"] == null)
{
Session.Add("Project_ATx", null);
}
else {
// Find the list item in the drop down that mataches the value in your session
ListItem li = ddProject.Items.FindByValue(Session["Project_ATx"]);
//Check to see if the list item was found in the drop down
//If it's found, then make it the selected item
if ( li != null )
li.Selected = true;
}
If you were storing the Text value in Session then use this method instead:
FindByText

If you store your value using:
Me.Session.Item("LastDdlValue") = Me.YourDdlValue.SelectedValue
You can use this code in Page_Load event when Not Me.Page.IsPostBack:
If Not IsNothing(Me.Session.Item("LastDdlValue")) Then
Me.YourDdlValue.SelectedValue = Me.Session.Item("LastDdlValue")
End If
Please note that you need to populate your DropDownList before setting its .SelectedValue.

FindByText is the best method, alternatively you can iterate through the items in the dropdown using for loop compare each item with the value saved in session. If they are equal set selected index
for(int i=0;i<dropdownlist1.Items.count;i++)
{
if(dropdownlist1.Items[i].Text==Session["Project_ATx"].ToString())//use dropdownlist1.Items[i].Value if you have stored the dropdownlist item value instead of text
{
dropdownlist1.SelectedIndex=i;
break;
}
}

Related

Passing Data from User Control in Master Page(s) to Content Page

I've looked at several similar questions to this one and right now I am trying to use the FindControl method without success.
My Web Forms application has several master pages. Common to all master pages is a search box and button in a nav user control at the top. I'm trying to grab the search term entered on the SearchResults page:
HtmlGenericControl topNavDiv = (HtmlGenericControl)Master.FindControl("topNavDiv");
Control topNav = (UserControl)Page.FindControl("topNav");
if (topNav != null)
{
TextBox searchBox = topNav.FindControl("searchBox") as TextBox;
if (searchBox != null)
{
Response.Write(searchBox.Text.Trim());
}
else
{
resultsPanel.Visible = false;
messagePanel.Visible = true;
}
}
In the first line, the topNavDiv variable is null. I was considering accessing the user control via a master page property, but with several different master pages I don't know how to determine the id of the master page as the search could be initiated from anywhere in the site...
UPDATE:
I was able to grab the topNav div, searchBox textbox as follows:
Control topNav = (UserControl)Master.FindControl("topNav");
if (topNav != null)
{
TextBox searchBox = topNav.FindControl("searchBox") as TextBox;
if (!String.IsNullOrEmpty(searchBox.Text))
{
Response.Write(searchBox.Text.Trim());
}
else
{
resultsPanel.Visible = false;
messagePanel.Visible = true;
}
}
The only problem is that the search box text entered is not being persisted.
If you need to keep the data out of the query string for some reason you could use a Property on your MasterPage.cs file.
public string SearchTerm
{
get
{
return searchBox.Text;
}
}
Then you can use that wherever you need to like this:
MasterPage master = (MasterPage)this.Master;
master.SearchTerm;
Since this is an Intranet site, I was able to utilize a query string parameter to obtain the search term as follows:
Nav with Search Box User Control:
<ul class="navbar-form navbar-left">
<li>
<asp:TextBox ID="searchBox" class="form-control col-lg-8"
placeholder="Search" runat="server"></asp:TextBox>
<asp:Button ID="searchButton" CssClass="btn btn-warning" Text="Search"
runat="server" OnClick="searchButton_Click" />
</li>
</ul>
User Control Code-Behind:
protected void searchButton_Click(object sender, EventArgs e)
{
Response.Redirect("~/Search/SearchResults.aspx?term="+searchBox.Text.Trim());
}
Search Results Page Code-Behind:
if (!Page.IsPostBack)
{
if (!String.IsNullOrEmpty(Request.QueryString["term"]))
{
term = Request.QueryString["term"].ToString();
Response.Write(term);
}
else
{
resultsPanel.Visible = false;
messagePanel.Visible = true;
}
}
What I would really like to know is if it is programmatically possible to determine in a page's code-behind, the identity of the master page of the requesting page?

Retrieving field values in ASP.net after checkbox has been selected

HI All - PLease refer the attached screen shot. The status and Role fields are enclosed in a panel for each check box.
On click of the submit button, only data for the selected check box should be picked up. Can you please help with a pseudo code how the data (Status and Role) for the first and third checkbox can be retrieved.
These controls are kept in a table. No grid view is being used.
Thanks for the help.
Yagya
All data will be returned to the server, but that's not a problem, just act on whatever the spec says.
I assume that the checkboxes are hardcoded <asp:Checkbox /> or <input type="checkbox" runat="server" /> controls, then it's simple:
Assuming <input type="checkbox" runat="server" id="reporting" /> then:
public override void OnLoad(Object sender, EventArgs e) {
if( this.reporting.Checked ) {
String status = this.reportingStatus.Value;
String role = this.reportingRole.Value;
// your logic here
} else if( this.assignment.Checked ) {
// etc
} else... // and so on
}

Gridview checkbox losing information during sorting

So I have this checkbox inside a gridview, and it is working properly for the most part. However, I am trying to implement column-sorting to the grid, and it is causing an issue with the checkbox. When I do my initial fetch from the database, it populates the checkboxes properly, but when I click on a column to sort by it, all of my checkboxes get cleared out.
It seems that this is a problem with the Databind being done by the gridview, but I'm not sure what I'm doing wrong. My research into the issue makes me feel like I have it right, but I don't know for sure (legacy code: I hate it).
<asp:GridView ID="UserListGrid" runat="server"
OnSorting="UserListGrid_Sort" AllowSorting = "True" AutoGenerateColumns="False"
AllowPaging="True" PageSize="25" OnRowDataBound="UserListGrid_RowDataBound"
OnPageIndexChanging="UserListGrid_PageIndexChanging">
.
.
.
<ItemTemplate>
<asp:CheckBox ID="ActiveCheck" runat="server" SortExpression="ActiveCheck"/>
</ItemTemplate>
.
.
.
protected void UserListGrid_Sort(object sender, GridViewSortEventArgs e)
{
// ViewState["CurTab"] = 0;
DataTable Data = myData.GetSessionRoster(TeamID);
DataView UserListView = new DataView(Data);
ViewState["SortDirection"] = myData.ConvertSortDirectionToSql(ViewState["SortDirection"] == null ? "" : ViewState["SortDirection"].ToString());
UserListView.Sort = e.SortExpression + " " + ViewState["SortDirection"];
UserListGrid.DataSource = UserListView;
UserListGrid.DataBind();
}
Is there anything obviously wrong with my sorting? I can provide more code if needed.
As requested, here is UserListGrid_RowDataBound
protected void UserListGrid_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType != DataControlRowType.DataRow)
{
return;
}
// See which users are active
CheckBox ActiveCheck = (CheckBox)e.Row.Cells[1].FindControl("ActiveCheck");
if (ActiveCheck != null)
{
ActiveCheck.Enabled = true;
if (e.Row.Cells[11].Text.Equals("1") && !Page.IsPostBack)
{
ActiveCheck.Checked = true;
ActiveCheck.DataBind();
}
}
}
It looks like you're populating checkboxes not from the data base, but corresponding to the contents of your cell 11 (whatever it is).
I appeal to this code line:
if (e.Row.Cells[11].Text.Equals("1") && !Page.IsPostBack)
While sorting you rebind your gridview, but you restrict populating and rebinding of your checkboxes on postback. This could be a reason for checkboxes loosing values.
I do not see where you are saving data of your checkBoxes. However, the good approach is to save all changes made by the end-user at every request to the server. As far as I see, the data stored in the DataTable. So, generally, you should browse through all grid rows, find CheckBoxes in them and save their values in this table. This should be done in the Page_Load method. This is necessary for the code in the UserListGrid_RowDataBound event handler to work properly.

How to get the latest selected value from a checkbox list?

I am currently facing a problem. How to get the latest selected value from a asp.net checkbox list?
From looping through the Items of a checkbox list, I can get the highest selected index and its value, but it is not expected that the user will select the checkbox sequentially from lower to higher index. So, how to handle that?
Is there any event capturing system that will help me to identify the exact list item which generates the event?
If I understood it right, this is the code I'd use:
protected void CheckBoxList1_SelectedIndexChanged(object sender, EventArgs e)
{
int lastSelectedIndex = 0;
string lastSelectedValue = string.Empty;
foreach (ListItem listitem in CheckBoxList1.Items)
{
if (listitem.Selected)
{
int thisIndex = CheckBoxList1.Items.IndexOf(listitem);
if (lastSelectedIndex < thisIndex)
{
lastSelectedIndex = thisIndex;
lastSelectedValue = listitem.Value;
}
}
}
}
Is there any event capturing system that will help me to identify the exact list item which generates the event?
You use the event CheckBoxList1_SelectedIndexChanged of the CheckBoxList. When a CheckBox of the list is clicked this event is called and then you can check whatever condition you want.
Edit:
The following code allows you to get the last checkbox index that the user selected. With this data you can get the last selected value by the user.
protected void CheckBoxList1_SelectedIndexChanged(object sender, EventArgs e)
{
string value = string.Empty;
string result = Request.Form["__EVENTTARGET"];
string[] checkedBox = result.Split('$'); ;
int index = int.Parse(checkedBox[checkedBox.Length - 1]);
if (CheckBoxList1.Items[index].Selected)
{
value = CheckBoxList1.Items[index].Value;
}
else
{
}
}
Below is the code which gives you the Latest selected CheckBoxList Item.
string result = Request.Form["__EVENTTARGET"];
string [] checkedBox = result.Split('$'); ;
int index = int.Parse(checkedBox[checkedBox.Length - 1]);
if (cbYears.Items[index].Selected)
{
//your logic
}
else
{
//your logic
}
Hope this helps.
Don't know about you, but as a user i wouldn't want the page to post back every time a checkbox item was checked.
This is the solution i would go with (jQuery):
Declare a server-side hidden field on your form:
<asp:HiddenField ID="HiddenField1" runat="server" EnableViewState="true" />
Then wire up client-side event handlers for the checkboxes to store checkbox clicked:
$('.someclassforyourcheckboxes').click(function() {
$('#HiddenField1').val($(this).attr('id'));
This is a lightweight mechanism for storing the ID of the "latest" checkbox clicked. And you won't have to set autopostback=true for the checkboxes and do an unecessary postback.
You dont HAVE to use jQuery - you can use regular Javascript, but, why do more work? =)
Then when you actually do the postback (on a submit button click i assume), just check the value of the hidden field.
Unless of course you WANT to postback on every checkbox click, but i can't envision a scenario in which you'd want this (maybe you're using UpdatePanel).
EDIT
The HTML of a checkbox list looks like this:
<input type="checkbox" name="vehicle" value="Bike" /> I have a bike
So, you can access three things:
Vehicle = $(this).attr('name');
Bike = $(this).attr('value');
I have a bike = $(this).html();
If you're trying to access the databound value, try the second technique.
Give that a try.

How to programmatically create and use a list of checkboxes from ASP.NET?

I have a page with a table of stuff and I need to allow the user to select rows to process. I've figured out how to add a column of check boxes to the table but I can't seem to figure out how to test if they are checked when the form is submitted. If they were static elements, I'd be able to just check do this.theCheckBox but they are programaticly generated.
Also I'm not very happy with how I'm attaching my data to them (by stuffing it in there ID property).
I'm not sure if it's relevant but I'm looking at a bit of a catch-22 as I need to known which of the checkboxes that were created last time around were checked before I can re-run the code that created them.
Edit:
I've found an almost solution. By setting the AutoPostBack property and the CheckedChanged event:
checkbox.AutoPostBack = false;
checkbox.CheckedChanged += new EventHandler(checkbox_CheckedChanged);
I can get code to be called on a post back for any check box that has changed. However this has two problems:
The call back is processed after (or during, I'm not sure) Page_Load where I need to use this information
The call back is not called for check boxes that were checked when the page loaded and still are.
Edit 2:
What I ended up doing was tagging all my ID's with a know prefix and stuffing this at the top of Form_Load:
foreach (string v in this.Request.Form.AllKeys)
{
if (v.StartsWith(Prefix))
{
var data = v.Substring(Prefix.Length);
}
}
everything else seems to run to late.
I'm going to assume you're using a DataList but this should work with and Control that can be templated. I'm also going to assume you're using DataBinding.
Code Front:
<asp:DataList ID="List" OnItemDataBound="List_ItemDataBound" runat="server">
<ItemTemplate>
<asp:CheckBox ID="DeleteMe" runat="server"/>
<a href="<%# DataBinder.Eval(Container, "DataItem.Url")%>" target="_blank">
<%# DataBinder.Eval(Container, "DataItem.Title")%></a>
</ItemTemplate>
</asp:DataList>
<asp:Button ID="DeleteListItem" runat="server" OnClick="DeleteListItem_Click" ></asp:Button>
Code Behind:
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadList();
}
protected void DeleteListItem_Click(object sender, EventArgs e)
{
foreach (DataListItem li in List.Items)
{
CheckBox delMe = (CheckBox)li.FindControl("DeleteMe");
if (delMe != null && delMe.Checked)
//Do Something
}
}
LoadList();
}
protected void LoadList()
{
DataTable dt = //Something...
List.DataSource = dt;
List.DataBind();
}
protected void List_ItemDataBound(object sender, DataListItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item)
{
string id = DataBinder.Eval(e.Item.DataItem, "ID").ToString();
CheckBox delMe = (CheckBox)e.Item.FindControl("DeleteMe");
if (delMe != null)
delMe.Attributes.Add("value", id);
}
}
}
First, make sure that each Checkbox has an ID and that it's got the 'runat="server"' in the tag.
then use the FindControl() function to find it.
For example, if you're looping through all rows in a GridView..
foreach(GridViewRow r in Gridview1.Rows)
{
object cb = r.FindControl("MyCheckBoxId");
if(r != null)
{
CheckBox chk = (CheckBox)cb;
bool IsChecked = chk.Checked;
}
}
Postback data is restored between the InitComplete event and the PreLoad event. If your checkboxes are not created until later then the checkboxes will play "catch up" with their events and the data will be loaded into the control shortly after it is created.
If this is to late for you then you will have to do something like what you are already doing. That is you will have to access the post data before it is given to the control.
If you can save the UniqueId of each CheckBox that you create then can directly access the post data without having to given them a special prefix. You could do this by creating a list of strings which you save the ids in as you generate them and then saving them in the view state. Of course that requires the view state to be enabled and takes up more space in the viewstate.
foreach (string uniqueId in UniqueIds)
{
bool data = Convert.ToBoolean(Request.Form[uniqueId]);
//...
}
Your post is a little vague. It would help to see how you're adding controls to the table. Is it an ASP:Table or a regular HTML table (presumably with a runat="server" attribute since you've successfully added items to it)?
If you intend to let the user make a bunch of selections, then hit a "Submit" button, whereupon you'll process each row based on which row is checked, then you should not be handling the CheckChanged event. Otherwise, as you've noticed, you'll be causing a postback each time and it won't process any of the other checkboxes. So when you create the CheckBox do not set the eventhandler so it doesn't cause a postback.
In your submit button's eventhandler you would loop through each table row, cell, then determine whether the cell's children control contained a checkbox.
I would suggest not using a table. From what you're describing perhaps a GridView or DataList is a better option.
EDIT: here's a simple example to demonstrate. You should be able to get this working in a new project to test out.
Markup
<form id="form1" runat="server">
<div>
<table id="tbl" runat="server"></table>
<asp:Button ID="btnSubmit" runat="server" Text="Submit"
onclick="btnSubmit_Click" />
</div>
</form>
Code-behind
protected void Page_Load(object sender, EventArgs e)
{
for (int i = 0; i < 10; i++)
{
var row = new HtmlTableRow();
var cell = new HtmlTableCell();
cell.InnerText = "Row: " + i.ToString();
row.Cells.Add(cell);
cell = new HtmlTableCell();
CheckBox chk = new CheckBox() { ID = "chk" + i.ToString() };
cell.Controls.Add(chk);
row.Cells.Add(cell);
tbl.Rows.Add(row);
}
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
foreach (HtmlTableRow row in tbl.Rows)
{
foreach (HtmlTableCell cell in row.Cells)
{
foreach (Control c in cell.Controls)
{
if (c is CheckBox)
{
// do your processing here
CheckBox chk = c as CheckBox;
if (chk.Checked)
{
Response.Write(chk.ID + " was checked <br />");
}
}
}
}
}
}
What about using the CheckBoxList control? I have no Visual Studio open now, but as far as I remember it is a DataBound control, providing DataSource and DataBind() where you can provide a list at runtime. When the page does a postback you can traverse the list by calling something like myCheckBoxList.Items and check whether the current item is selected by calling ListItem.Selected method. This should work.
Add them in an override of the CreateChildControls method of the Page. Be sure to give them an ID! This way they get added to the control tree at the correct time.
IMHO The best way would be to use DataBound Templated Control though, i.e. something like a ListView (in .NET 3.5). then in pageload after postback traverse all items in the databound control and use item.FindControl to get at the actual checkbox.
What I ended up doing was tagging all my ID's with a know prefix and stuffing this at the top of Form_Load:
foreach (string v in this.Request.Form.AllKeys)
{
if (v.StartsWith(Prefix))
{
var data = v.Substring(Prefix.Length);
}
}
everything else seems to run to late.

Resources