Changing Radiobutton selected in Gridview - asp.net

I have a gridview Template field in which there are 3 radio buttons. Once is checked and other 2 are disabled. Now the problem is if one radio button is checked and a button is clicked next time that radio button must be disabled and another radio button must be enabled for that particular row. Could you please help in this ?
foreach (GridViewRow gr in all_day_non_prod_GridView.Rows)
{
check1 = ((RadioButton)gr.FindControl("first")).Checked;
check2 = ((RadioButton)gr.FindControl("reminder")).Checked;
check3 = ((RadioButton)gr.FindControl("completed")).Checked;
if (check1)
{
reminder = "First";
n = 1;
break;
}
else if (check2)
{
reminder = "Second";
n = 2;
break;
}
else
{
reminder = "Completed";
n = 3;
break;
}
}

So I think you will want to use CheckedChanged event with your check box. This is how I use mine in one of my applications.
protected void cbFirstCheckBox_CheckedChanged(object sender, EventArgs e)
{
//this helps you find the row and control in the gridview
GridViewRow gvr = (GridViewRow)(sender as Control).Parent.Parent;
CheckBox firstCheckBox = ((CheckBox)gvr.FindControl("cbSecondCheckBox"));
CheckBox secondCheckBox = ((CheckBox)gvr.FindControl("cbSecondCheckBox"));
//I believe you said you want to disable one then enable the 2nd one.
firstCheckBox.Enabled = false;
secondCheckBox.Enabled = true;
}
Then in your HTML you want to put this.
<asp:CheckBox ID="cbFirstCheckBox" runat="server" OnCheckedChanged="cbRemoveActive_CheckedChanged" AutoPostBack="true" Enabled="false"/>
So now, once you click the first check box, the 2nd checkbox will be enabled and the first checkbox will be disabled. You set the AutoPostBack to true so the page refreshes. I believe this is what you are wanting. You will be able to use this technique to do the other checkboxes as well. I hope this helps.
EDIT: I just saw that you used radio buttons. You should still be able to do the same just substituting CheckBox for RadioButton's. I have not tested the above but I think it will lead you in the right direction.
Another Edit: You may be able to actually keep the foreach loop you have. That should also work.
protected void rbFirstButton_CheckedChanged(object sender, EventArgs e)
{
foreach (GridViewRow gr in all_day_non_prod_GridView.Rows)
{
RadioButton rbFirstButton = ((RadioButton)gv.FindControl("rbFirstButton"));
RadioButton rbSecondButton = ((RadioButton)gv.FindControl("rbSecondButton"));
rbFirstButton.Enabled = false;
rbSecondButton.Enabled = true;
}
}
Last Edit: You can't have the foreach, it will enable all the checkboxes, not only on the row you want.. the code below is what I have tested and it works.
protected void rbOne_CheckedChanged(object sender, EventArgs e)
{
GridViewRow gvr = (GridViewRow)(sender as Control).Parent.Parent;
RadioButton rbOne = ((RadioButton)gvr.FindControl("rbOne"));
RadioButton rbTwo = ((RadioButton)gvr.FindControl("rbTwo"));
RadioButton rbThree = ((RadioButton)gvr.FindControl("rbThree"));
rbOne.Enabled = false;
rbTwo.Enabled = true;
rbThree.Enabled = true;
}
I believe that this is what you're looking for. I hope this helps.

Related

Setting Button Properties in ListView ItemTemplate

I have a ListView which displays event bookings. If there is a time slot available, I want to make a booking button visible beside that data item. I have tried doing this in both the OnItemCreated and OnItemDataBound event handlers to no avail.
In this particular scenario, there are four results and all are available. However, the button only appears beside the last result. It's like something is being overwritten. I tried setting the ID property to something different in each round of the loop but that failed at runtime.
I also tried flipping the logic by setting the visibility of the button to false in the markup initially - three buttons would appear and no button beside the last data item.
I originally tried storing the Button control in ViewState and got the "not serializable" error. So I switched to storing the object in Session state.
Can someone point me in the right direction?
<ItemTemplate>
...
<asp:Button ID="reserveButton" Text="Book Now" Visible="false"
OnClick="ReserveButton_Click" runat="server" />
</ItemTemplate>
// After the DataBind() method in the search button handler
...
int rowCount = resultsDS.Tables[0].Rows.Count;
for (int i = 0; i < rowCount; i++)
{
if (resultsDS.Tables[0].Rows[i]["Available"].ToString().Contains("Available Time Slots"))
{
reserveButton = Session["ReserveButton"] as Button;
reserveButton.Visible = true;
}
}
...
protected void ResultsList_ItemCreated(object sender, ListViewItemEventArgs e)
{
if (e.Item is ListViewItem)
{
reserveButton = e.Item.FindControl("reserveButton") as Button;
Session["ReserveButton"] = reserveButton;
}
}
For the benefit of others, I was able to solve this as follows:
protected void ResultsList_ItemDataBound(object sender, ListViewItemEventArgs e)
{
if (e.Item is ListViewItem)
{
DataRowView row = (DataRowView)e.Item.DataItem;
if (row["Available"].ToString().Contains("Available Time Slots"))
{
Button reserveButton = e.Item.FindControl("reserveButton") as Button;
reserveButton.Visible = true;
}
}
}

What to type in ASP.NET when you want to make sure that a button is clicked

I don't seem to know how to correctly write bn_pwd.Click and to make it work. Please help me.
protected void bn_pwd_Click(object sender, EventArgs e)
{
if (bn_pwd.Click == true)
{
lb_showpwd.Visible = true;
tb_Spwd.Visible = true;
lb_showcfmpwd.Visible = true;
tb_Scfmpwd.Visible = true;
}
else
{
lb_showpwd.Visible = false;
tb_Spwd.Visible = false;
lb_showcfmpwd.Visible = false;
tb_Scfmpwd.Visible = false;
}
}
When the bn_pwd_Click function is fired, it means that the button was clicked. What you want to do with bn_pwd.Click == true ?
Maybe you should use a variable to store the state of the controls you want to apply.
What you have will work (minus some unnecessary code), assuming you have a button with OnClick="bn_pwd_Click":
<asp:Button ID="bn_pwd" OnClick="bn_pwd_Click" Text="Submit" runat="server" />
Alternatively, you can declare the Click event in the code behind (and not have it in the code-front as above). Personally, I like having it on the code-front side.
bn_pwd.Click += bn_pwd_Click;
Now, when the button is clicked, the page will post-back (your Page_Load will execute again), and then bn_pwd_Click will execute. So you only need this:
protected void bn_pwd_Click(object sender, EventArgs e)
{
lb_showpwd.Visible = true;
tb_Spwd.Visible = true;
lb_showcfmpwd.Visible = true;
tb_Scfmpwd.Visible = true;
}
Because that function only ever runs when the button is clicked. I assume the visibilities of all of those controls should be set to false to begin with. Either in code front or in Page_Load.
From your question, it seems like you need to review the ASP.NET Page Life Cycle and could also benefit from some tutorials, like at ASP.net.

CheckBox handling oncheck changed in ASP.net

i had a DataList view which i add a check box in the Item Template
i want each item i select to increase some counter for examble once it's checked ..
i used the following code to handle that ,but the event function is never accessed ?!
protected void selectItemCheckBox_CheckedChanged(object sender, EventArgs e)
{
int selected = 0;
foreach (DataListItem i in DataList1.Items)
{
CheckBox chk = (CheckBox)i.FindControl("selectItemCheckBox");
if (chk.Checked)
{
selected++;
}
selectedItemCount.Text = Convert.ToString(selected);
}`
}
Currently you're looping over every checkbox for every checked checkbox which is inefficient and depending on your other code, may be causing trouble.
You're better off incrementing for each checkbox individually.
...DataList...
<ItemTemplate>
<asp:CheckBox id="selectItemCheckBox" runat="server"
AutoPostBack="True"
OnCheckedChanged="selectItemCheckBox_CheckedChanged" />
</ItemTemplate>
...DataList...
After a box is checked, update the total for just that checkbox using sender
protected void selectItemCheckBox_CheckedChanged(object sender, EventArgs e)
{
// Parse the total selected items from the TextBox.
// You may consider using a Label instead, or something non-editable like a hidden field
int totalChecked;
if (int.TryParse(selectedItemCount.Text, out totalChecked) = false)
totalChecked = 0;
// Get a reference to the CheckBox
CheckBox selectItemCheckBox = (CheckBox)sender;
// Increment the total
if (selectItemCheckBox.Checked == true)
totalChecked++;
// Put back in the TextBox
selectedItemCount.Text = totalChecked.ToString();
}

ASP.NET: How to access a dynamically created control

I'm creating a bunch of Checkboxes dynamically:
CheckBox chkRead = new CheckBox();
chkRead.ID = "chk1";
chkRead.AutoPostBack = true;
chkRead.CheckedChanged += new EventHandler(CheckBox_CheckedChanged);
CheckBox chkPost = new CheckBox();
chkRead.ID = "chk2";
chkPost.AutoPostBack = true;
chkPost.CheckedChanged += new EventHandler(CheckBox_CheckedChanged);
protected void CheckBox_CheckedChanged(object sender, EventArgs e)
{
CheckBox chk = (CheckBox)sender;
}
What I want to do is the following:
When I check the chkPost CheckBox I want the chkRead CheckBox to be checked as well
In the CheckBox_CheckedChanged event I only have access to the CheckBox that was clicked
but I don't know how to check the other checkbox from that event.
This is from memory, but you could do something like this:
protected void CheckBox_CheckedChanged(object sender, EventArgs e)
{
CheckBox chk = (CheckBox)sender;
CheckBox chkPost = (CheckBox) chk.NamingContainer.FindControl("chk2");
CheckBox chkRead = (CheckBox) chk.NamingContainer.FindControl("chk1");
if(chk == chkPost && chk.Checked)
{
chkRead.Checked = true;
}
}
This is assuming you want to do all this in code-behind, after postback. If you want to do it in javascript, that's a different question.
This also assumes that chk1 and chk2 are in the same naming container. If they aren't, things will get complicated.
Since it is your code that creates the checkboxes, you can store their references in a list or dictionary and retrieve them by id when needed.
If you want to do it dynamically you can add an attribute to the checkboxess you are interested in-- you can then loop over the Page.Controls collection and test that the control you are looping over has that attribute and then you can check, or uncheck it.
some pseudo code:
foreach(var control in Page.Controls)
if(typeof(Control) is CheckBox and ((CheckBox)control).Attributes["myAttr"] != null)
//check or uncheck it
In reading your comment about nested controls-- this might be a bit of a hassle-- I tend to agree with Igor, that you should put the id's in a collection as they are being added dynamically.
Could you paste code where you are creating these checkboxes? Is it "OnInit" or somewhere else? Are you putting these checkboxes in container, do you store these controls as global variables or create them in method?

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