ASP.NET: Problem with CheckBoxList and OnSelectedIndexChanged - c#

I'm having a problem with CheckBoxList and OnSelectedIndexChanged:
<asp:UpdatePanel runat="server">
<ContentTemplate>
<asp:CheckBoxList
id="lstWatchEType"
runat="server"
DataTextField="DescriptionText"
DataValueField="Id"
AutoPostBack="true"
OnSelectedIndexChanged="lstWatchEType_SelectedIndexChanged"/>
</ContentTemplate>
</asp:UpdatePanel>
This is populated in Page_Load (!IsPostBack)
public static void PopulateWatchEType(CheckBoxList list, Guid clientId)
{
OffertaDataContext db = new OffertaDataContext();
var ds = (from e in db.EnquiryTypes select new {
Id = e.Id,
DescriptionText = e.DescriptionText,
IsWatching = !db.WatchXrefEnquiryTypes.Any(f => f.ClientId.Equals(clientId) && f.EnquiryTypeId==e.Id && f.Inbox==false)
});
list.DataSource = ds;
list.DataBind();
foreach(var item in ds)
{
list.Items.FindByValue(item.Id.ToString()).Selected = item.IsWatching;
}
}
My problem is in:
protected void lstWatchEType_SelectedIndexChanged(Object sender, EventArgs e)
{
ListItem item = lstWatchEType.SelectedItem;
...
}
Where item is always the first element in the list???

The selected item property will return the selected item with the lowest index inside of the list. If the first item is selected, then it will return the first item.
To get the latest selected item, perhaps you can create a global variable and set that variable on index changed. You can create a ListItem collection that first holds all of the initial selected indexes like Kirtan suggested, then create a new collection that holds all of the newest selections whenever the selected index changes. Match the two lists, and whatever item is in the new list that is not in the older list is your latest selected index.
Hope this helps.

Related

Programming gridview checkboxes to auto check relevant rows

I want to program the checkboxes so that if a row is selected, the program will read the value in the first column of the gridview row and automatically check all rows that also have that value in their first column. I was able to do this using an array to store the value and running through each row, checking if this value was a match. If it matched, the checkbox was checked. This worked but was a very limited solution. When I tried to reverse the action, it simply rechecked that value automatically because that value was still in the array and I did not know how to distinguish between a check or un-check action. It was solely based on a change event.
int count = 0;
foreach (GridViewRow gvrow in GridView1.Rows)
{
CheckBox chk = (CheckBox)gvrow.FindControl("chkRow");
if (chk.Checked)
{
count++;
}
}
string [] dnum = new string[count];
int counter = 0;
foreach (GridViewRow row in GridView1.Rows)
{
CheckBox myCheckBox = row.FindControl("chkRow") as CheckBox;
if (myCheckBox.Checked)
{
if (counter > 0)
{
int number = counter - 1;
if (row.Cells[1].Text != dnum[number])
{
dnum[counter] = row.Cells[1].Text;
counter++;
}
}
else
{
dnum[counter] = row.Cells[1].Text;
counter++;
}
}
}
return dnum;
}
The array dnum should return the first column values for the checked rows . With this I can run through each row and check if any checkboxes need to be checked.
foreach (GridViewRow gvrow in GridView1.Rows)
{
CheckBox ChkBox = (CheckBox)gvrow.FindControl("chkRow");
if (ChkBox.Checked == true)
{
foreach (string s in first)
{
if (gvrow.Cells[1].Text == s)
{
ChkBox.Checked = true;
}
}
}
But now I am unable to figure out how to reverse the process, i.e when I uncheck one, all with the same first column value must uncheck, instead it just rechecks because that value is still in the array. I am open to completely different methods.
Many thanks,
Nicolas
I don't clearly understand your problem, Maybe you're looking for this?
use this code instead of your old one in check ChkBox loop.
if (gvrow.Cells[1].Text == s)
{
ChkBox.Checked = !ChkBox.Checked;
}
With ChkBox.Checked = !ChkBox.Checked, It'll reverse value in checkbox.
If it was true, It'll become false. If it was false, It'll become true.
Will just give another example, not sure on how you are implementing at your code so here it goes...
For example you have your gridview as below:
<asp:GridView ID="GridView1" runat="server">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox ID="CheckBox1"
OnCheckedChanged="CheckBox1_Click"
AutoPostBack="True" runat="server" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
And in your code behind..
mockData data below is just sample data for our gridview to demonstrate the check and un-check of same value based on selected checkbox property and column[1] value.
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
var mockData = new[] {"1", "1", "2", "1", "3", "2"};
GridView1.DataSource = mockData;
GridView1.DataBind();
}
}
protected void CheckBox1_Click(object sender, EventArgs e)
{
var chkBox = (CheckBox) sender;
var selectedRow = chkBox.Parent.Parent;
var itemValue = ((GridViewRow)selectedRow).Cells[1].Text;
foreach (var chkItem in GridView1.Rows.Cast<GridViewRow>()
.Where(item => item.Cells[1].Text == itemValue)
.Select(item => item.Cells[0].FindControl("CheckBox1")).OfType<CheckBox>())
{
chkItem.Checked = chkBox.Checked;
}
}
}
If I click on checkbox in one row with value of "1", All rows with value of "1" should be automatically set to the property of selected checkbox.
Let me know if I misunderstood your requirement. You can apply to your code and let me know if it works :-) cheers.

databinding issue asp.net dropdown list

Im trying to bind my drop down list, i think is beacuse my asp code on the front end is not bound somehow
aspx
<asp:Label ID="Label2" runat="server" />
<asp:DropDownList Width="150px" ID="ddLocation" runat="server"
AppendDataBoundItems="True"
DataTextField="Name"
DataValueField="Name" AutoPostBack="True" >
</asp:DropDownList>
c# code
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
Label0.Text = "Specialities";
Label1.Text = "Category";
Label2.Text = "Locations";
ddSpec.Items.Insert(0, new ListItem("Select a spec", "0"));
ddCategory.Items.Insert(0, new ListItem("Select a Category", "0"));
ddLocation.Items.Insert(0, new ListItem("<Select a Location>", "0"));
populattePage();
}
}
public void populattePage()
{
getlocation();
// getCategory()
}
public static void getlocation()
{
DataClasses_DataContext dc = new DataClasses_DataContext();
List<string> locations = (
from a
in dc.Locations
select a.Name).ToList();
DropDownList ddLocation = new DropDownList();
ddLocation.DataSource = locations;
ddLocation.DataValueField = "ID";
ddLocation.DataTextField = "Name";
ddLocation.SelectedIndex = 0;
ddLocation.DataBind();
}
I now have the Error """"DataBinding: 'System.String' does not contain a property with the name 'Name'.""" the code in the """page load""" class adds items to the drop downs however when i call the get locations class I get this error, Please help thanks in advance
There are two issues here. First - if you are going to use 2 properties of the Location object, you should use this object as a data source. No point to extract separate list of strings for this:
ddLocation.DataSource = dc.Locations.ToList();
This will resolve your exception. Also this line:
DropDownList ddLocation = new DropDownList();
should not be here, just remove it. You already have your drop down initialized.
Second issue - if you want some default item to appear in the list, you should insert it after the data binding:
populattePage();
ddLocation.Items.Insert(0, new ListItem("<Select a Location>", "0"));
ListItems have the properties "Text" and "Value". So when you create one, you can only use those properties for the drop down list text/value fields. You need to change
<asp:DropDownList Width="150px" ID="ddLocation" runat="server"
AppendDataBoundItems="True"
DataTextField="Text"
DataValueField="Value" AutoPostBack="True" >
</asp:DropDownList>
A simple way to get your location would be
List<ListItem> locations = (from a in dc.Locations
select new ListItem()
{
Text = a.Name,
Value = a.Name
}).ToList();
Then append that to your list.
So the problem is the data source you're binding to is primarily string. When you set the DataValueField and DataTextField properties, it calls the reflector and asks the object its being bound to, to give it the property. Since I'm assuming the a.Name in the query is a string, it would not have a "Name" or "Id" property. A simple solution to this would be to create an ID and Name property.
This might help illustrate what I'm trying to say. (also please camel-case your function names if you plan to do C# it helps us maintenance programmers :))
public static void GetLocation()
{
DataClasses_DataContext dc = new DataClasses_DataContext();
var locations = (
from a
in dc.Locations
select new { Name = a.Name, Id = a.Id }).ToList(); // this can be Id = a.Name or whatever too
DropDownList ddLocation = new DropDownList();
ddLocation.DataSource = locations;
ddLocation.DataValueField = "ID";
ddLocation.DataTextField = "Name";
ddLocation.SelectedIndex = 0;
ddLocation.DataBind();
}
Hope that helps!

Dropdown List will not populate

I'm not sure how to correct the following problem. I have dropdown list that has a object data source. Then in the code there is a method like this
void InitPageData()
{
MembershipUser user = Membership.GetUser();
DataSetTableAdapters.MemberInfoTableAdapter da = new DataSetTableAdapters.MemberInfoTableAdapter();
DataSet.MemberInfoDataTable dt = da.GetMember((Guid)user.ProviderUserKey);
if (dt.Rows.Count == 1)
{
DataSet.MemberInfoRow mr = dt[0];
//rank.Text = mr.rank;
//position.Text = mr.position;
UserName.Text = user.UserName;
...
}
This method populates form fields on the page. What I'm trying to do is to have the rank dropdown list populated from the ods but use this method above to populate the selected item of the rank dropwon list with the line rank.Text = mr.rank. In this example the the line of code that throws the error is commented out otherwise it throws this: "'rank' has a SelectedValue which is invalid because it does not exist in the list of items.
Parameter name: value".
I've chaned the code to rank.DataTextFiled = mr.rank and rank.DataValueField = mr.rankid.ToString() but this threw another error: "DataBinding: 'System.Data.DataRowView' does not contain a property with the name 'Star'." "Star" is the value of the mr.rank.
Here is what the dropdown list and the ods look like:
<asp:DropDownList runat="server" ID="rank" CssClass="txtfield" DataSourceID="ODCRanks"
DataTextField="Rank" DataValueField="ID" AppendDataBoundItems="True">
<asp:ListItem Text="--- Select a Rank ---" Value="-1" />
<asp:ObjectDataSource ID="ODCRanks" runat="server"
OldValuesParameterFormatString="original_{0}" SelectMethod="GetRanks"
TypeName="RanksTableAdapters.RankTableAdapter"></asp:ObjectDataSource>
You should try adding data columns to your data tables (with ID and Rank being the column name) so that the data can be binded to control.
The Text property sets it by value.
See http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.listcontrol.text.aspx
You seem to have what will be the text associated with the value and you want to set that as the selected item. I guess this mostly because your value collection is bound to something called ID and I figure a rank of Star isn't an ID.
If Star is what will show up as something in DataTextField, use the items collection FindByText method to select it.
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.listitemcollection.findbytext.aspx
Example
ListItem li = DropDownList1.Items.FindByText("one");
if (li != null) li.Selected = true;
If Star is indeed an ID, then check that the collection is fully loaded before trying to select anything in it.
try something like
rank.SelectedIndex = rank.Items.IndexOf(rank.Items.FindByText(mr.rank));

Ranking Priority using DropDownList in C#

My idea is to build a Ranking Priority using a DropDownList ASP server control.
Here's my setup: I have 3 DropDownLists and it has 3 items ("First", "Second", "Third") on each DropDownLists. When I have chosen the 1st DropDownList assuming the item I have selected is "First" and on the 2nd DropDownList by default its SelectedItem is "First" also the item of the 1st DropDownList on which I have selected must be swapped on the 2nd DropDownList.
In short there would be unique SelectedItems on each DropDownList and in every SelectedIndexChanged event occuring there would be swapping of items on the 3 DropDownLists. That's what my Ranking Priority would be.
My question would be, how can I swapped a previous item on the DropDownList going from one another DropDownList where I have selected on and placed a new item?
Here's my code:
protected void DropDownListPriority_SelectedIndexChanged(object sender, EventArgs e)
{
DropDownList ddlRank = (DropDownList)sender;
int swapIndex;
string sameDdlSelectedItemID;
//Get list of DDLs
List<DropDownList> ddlRankList = new List<DropDownList>();
ddlRankList.Add(ddlBiometricNoOrder);
ddlRankList.Add(ddlDateTimeOrder);
ddlRankList.Add(ddlTransactionTypeOrder);
//Store ListItems for DDL
List<string> strRankList = new List<string>();
strRankList.Add("First");
strRankList.Add("Second");
strRankList.Add("Third");
//Holds temp. DDL
List<DropDownList> tempRankList = new List<DropDownList>();
//Remove the '<-- Select -->' item when ddl is changed
if(ddlRank.Items.Contains(new ListItem("<-- Select -->")))
ddlRank.Items.RemoveAt(0);
//Loop on each List<T>
for(int x = 0; x < ddlRankList.Count; x++)
{
for (int y = 0; y < ddlRankList.ElementAt(x).Items.Count; y++)
{
if (ddlRankList.ElementAt(x).Items[y].Text != ddlRank.SelectedItem.Text)
{
//Check amongst the unselected item to be changed (int swapIndex)
swapIndex = Convert.ToInt32(ddlRankList.ElementAt(x).Items[y].Value);
}
}
}
foreach (DropDownList ddl in ddlRankList)
{
foreach (string strRank in strRankList)
{
if (ddlRank.SelectedItem.Text == ddl.SelectedItem.Text)
{
sameDdlSelectedItemID = ddl.ID;
//Set the ddl SelectedIndex
ddl.SelectedIndex = //This is my question;
}
}
}
}
I see that you have considered an approach where the lists are repopulated at server end. Is there any specific reason for it as server postbacks could be costly. Instead why don't you consider a jquery/javascript based solution where the lists are manipulated based on user selected values.
You can implement the event based model as well. Refer this

ListView containing CheckBoxList - Selected items not showing as checked

I have a ListView with an EditItemTemplate that calls a method onItemEditing.
Within my ListView I have a CheckBoxList bound using LINQ.
In my onItemEditing method, I'm trying to check certain CheckBoxes if they are present in a look up table that links users with sectors.
However, when I load the EditItemTemplate none of the CheckBoxes are checked even though I've set them as selected in the onItemEditing method.
Here's the Method:
protected void onItemEditing(object sender, ListViewEditEventArgs e)
{
ListView1.EditIndex = e.NewEditIndex;
ListView1.DataBind();
int regId = Convert.ToInt32(((Label)ListView1.Items[e.NewEditIndex].FindControl("LblRegId")).Text);
CheckBoxList cbl = (CheckBoxList) ListView1.Items[e.NewEditIndex].FindControl("chkLstSectors");
//test to see if forcing first check box to be selected works - doesn't work
cbl.Items[0].Selected = true;
SqlConnection objConn = new SqlConnection(ConfigurationManager.ConnectionStrings["DaresburyConnectionString"].ToString());
SqlCommand objCmd = new SqlCommand("select * from register_sectors where register_id= " + regId, objConn);
objConn.Open();
SqlDataReader objReader = objCmd.ExecuteReader();
if (objReader != null)
{
while (objReader.Read())
{
ListItem currentCheckBox = cbl.Items.FindByValue(objReader["sector_id"].ToString());
if (currentCheckBox != null)
{
currentCheckBox.Selected = true;
}
}
}
}
Any ideas how to get around this?
The problem was the listView was being bound again after the checkboxlist was bound.
I removed the binding and it works!
I hope I'm not too late with my answer ;)
I have a CheckBoxList in a ListView which should DataBind like the other controls. The value in the database is a calculated value from this enumeration:
public enum SiteType
{
Owner = 1,
Reseller = 2,
SubReseller = 4,
Distributor = 8
Manufacturer = 16,
Consumer = 32
}
If the value is 24 this means Distributor and Manufacturer (8 + 16).
I added a HiddenField to the EditItem in my ListView for databinding the value:
<EditItemTemplate>
<tr>
<td>
<asp:CheckBoxList ID="cblSiteTypes" runat="server" RepeatLayout="Flow"
DataSourceID="ObjectDataSource4" DataTextField="Key" DataValueField="Value" />
<asp:HiddenField ID="hfSiteTypes" runat="server" Value='<%# Bind("SiteType") %>' OnDataBinding="hfSiteTypesBnd" />
</td>
</tr>
<!-- other data... -->
</EditItemTemplate>
The CheckBoxList is filled through another DataSource, which returns a Dictionary object with the data from the enumeration. In code behind I use the OnDataBinding method of the HiddenField for the selection:
protected void hfSiteTypesBnd( object sender, EventArgs e )
{
// read the value
HiddenField hf = (HiddenField)sender;
short val = Convert.ToInt16( hf.Value );
// find the checkboxlist
CheckBoxList cblSiteTypes = (CheckBoxList)hf.Parent.FindControl( "cblSiteTypes" );
// clear the selection (may be not needed)
cblSiteTypes.ClearSelection();
// for each item
foreach ( ListItem li in cblSiteTypes.Items )
{
// get the value from each item and...
short v = Convert.ToInt16( li.Value );
// ...look up whether this value is matching or not
if ( ( val & v ) == v ) li.Selected = true;
}
}
Et voilĂ !

Categories

Resources