Adding RadComboBox to RadGrid Edit - asp.net

I have added a RadControl, RadGrid and I need to add a radComboBox in the edit mode.
When user clicks on the radComboBox, I need to get both "text" and "value" of the radComboBox to save to table when user updates values.
<telerik:RadComboBox ID="RadComboBox1" Runat="server"
DataSourceID="SqlDataSource1" DataTextField="docCategoryName"
DataValueField="docCategoryID" Height="200px" Skin="Vista">
When user selects from the radComboBox, I need to get the value of DataTextField & DataValueField into a HiddenField.

The approach described by Program.X is very good. This, of course, works if you're using a RadCombobox inside of a GridTemplateColumn in RadGrid.
RadGrid also provides a built-in GridDropDownColumn that can automatically render a RadCombobox during edits. If you choose to use the built-in column type, you need to programmatically set the client-side event handlers for the rendered RadGrid, like this:
protected void RadGrid1_ItemCreated(object sender, Telerik.Web.UI.GridItemEventArgs e)
{
//Find GridEditableItems when in Edit mode
if (e.Item is GridEditableItem && e.Item.IsInEditMode)
{
//Get reference to item (i.e. Row)
var item = e.Item as GridEditableItem;
//Get reference to auto-generated RadCombobox in
//specific column (in this case, a column called Title)
var rcb = item["Title"].Controls[0] as RadComboBox;
if (rcb == null)
return;
//Customize the RadCombobox properities
rcb.OnClientSelectedIndexChanged = "onselectedindexchanged";
}
}
Where "onselectedindexchanged" is the name of a client-side JavaScript function on your page designed to handle the RadCombobox event.
Either of these approaches should enable you to achieve your goal.

Telerik are the best people to help you with this, but from their site (and from memory):
http://www.telerik.com/help/aspnet-ajax/combo_clientsideonclientselectedindexchanged.html
If you have your radCombo:
<telerik:RadComboBox
ID="RadComboBox1"
runat="server"
OnClientSelectedIndexChanged="OnClientSelectedIndexChanged">
</telerik:RadComboBox>
With your JS event:
<script language="javascript" type="text/javascript">
function OnClientSelectedIndexChanged(sender, eventArgs)
{
var item = eventArgs.get_item();
// get the text and value elements
var text=item.get_text();
var val=item.get_value();
$('#hiddenField').val(val);
}
</script>
Where hiddenField is the ID of the hidden field.

Related

radio button list in repeater control

I have a repeater control in my page. I need to have a radio button in all the rows(Item template) on checking an radio button the remaining radio buttons must unchecked.
How to do this?
Thanks in advance,
Tor
Unfortunately, it's a known bug ( http://support.microsoft.com/kb/316495 ) that the GroupName property doesn't work as expected when used in a Repeater. The problem is that the Repeater implements the INamingContainer interface which requires all nested controls to have a unique name when rendered out to HTML. This causes the radio buttons to break because in order for them to work properly they must have identical names.
There are 2 work-arounds that I've come across:
1 - The first is a client-side javascript solution. It was provided by Microsoft support. Or an easier to read version here.
The instructions are as follows. Include the following javascript in the HEAD:
function SetUniqueRadioButton(nameregex, current)
{
re = new RegExp(nameregex);
for(i = 0; i < document.forms[0].elements.length; i++)
{
elm = document.forms[0].elements[i]
if (elm.type == 'radio')
{
if (re.test(elm.name))
{
elm.checked = false;
}
}
}
current.checked = true;
}
Now the function needs to be linked to the Radio Buttons in the OnDataItemBound event of the repeater. Replace "RadioButton" with the name of your RadioButton control and "RadioGroup" with the GroupName you have chosen:
protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType != ListItemType.Item && e.Item.ItemType != ListItemType.AlternatingItem) return;
RadioButton rb = (RadioButton) e.Item.FindControl("RadioButton");
string script = "SetUniqueRadioButton('Repeater1.*RadioGroup',this)";
rb.Attributes.Add("onclick", script);
}
2 - The second solution is a server-side solution using a custom usercontrol that inherits from RadioButton. The tutorial and source code can be downloaded here: http://www.codeproject.com/KB/webforms/How_group_RButtons.aspx
Just add a OnCheckedChanged event to the radio button, loop all the radiobuttons in the repeater to uncheck them. You can use UpatePanel if you do not want postback.
.aspx
<asp:Repeater ID="Repeater1" runat="server" >
<ItemTemplate>
<asp:RadioButton ID="RadioButton1" runat="server" OnCheckedChanged="RadioButton1_OnCheckedChanged" AutoPostBack="true" />
</ItemTemplate>
</asp:Repeater>
.cs
protected void RadioButton1_OnCheckedChanged(object sender, EventArgs e)
{
foreach (RepeaterItem item in Repeater1.Items)
{
RadioButton rbtn = (RadioButton)item.FindControl("RadioButton1");
rbtn.Checked = false;
}
((RadioButton)sender).Checked = true;
}
I know this is old, but the reason for the buttons not working is because the name attribute is being overwritten. If using jQuery, you could assign the radio button to a class then set the name attribute to override the new name.
$('.MyRadioClass').attr("name","MyFixedName");
Another simpler alternative, where no fancy formatting is required, is to use a RadioButtonList:
<asp:RadioButtonList ... />

CheckedChanged EventHandler of dynamically added Checkboxes not firing inside UpdatePanel of a Repeater

I´ve read most posts here but i can´t figure out why the "CheckedChanged" Event is not firing. Here is my situation.
I´m using a Repeater to generate Items out of a Database. Each ReapeaterItem should include an UpdatePanel, because i have to Update the Controls inside the UpdatePanel and do not want to reload the complete page. Inside these dynamically generated UpdatePanels (each RepeaterItem has one) i´m adding up to three Checkboxes dynamically (based on the Database). These Checkboxes need to fire the "CheckedChanged" event, because on some conditions i want to enable/disable/check/uncheck Checkbox1, 2 or 3 based on business logic. ... Hope you got this so far. I´m adding all Controls and have the EventHandler Added. But the generated Code does not reflect the Event Handler. I tried OnItemDataBound, OnItemCreated, PreRender, ... Events to add the Eventhandler too, but i was not able to find the CheckBox-Control with the ID.
I´m totally lost with this and on the way to use Buttons instead of Checkboxes. From what i read so far is that with Buttons i can use the CommandName from the Button and the ItemCommand-Event from the Repeater to get a workaround, but then i need to reflect the "Check" on the Page in some way.
btw, every Repeater (8) sits inside an ajaxtoolkit-accordion control.
Here i give you some Code:
aspx-Page
<asp:Repeater ID="RepeaterAccordionPane2" runat="server">
<ItemTemplate>
HTML Stuff<%# DataBinder.Eval(Container.DataItem, "Header")%>HTML Stuff<%# DataBinder.Eval(Container.DataItem, "Beschreibung")%></td>
<asp:UpdatePanel ID="UpdatePanel2" runat="server" UpdateMode=Conditional>
<ContentTemplate>
</ContentTemplate>
</asp:UpdatePanel>
HTML Stuff
</ItemTemplate>
</asp:Repeater>
Here is the Page_Load Part
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
dvAlleArtikel = new System.Data.DataView(...Database...);
[... some other code here ...]
RepeaterAccordionPane2.DataSource = dvAlleArtikel;
//RepeaterAccordionPane2.ItemCreated +=new RepeaterItemEventHandler(RepeaterAccordionPane2_ItemCreated);
//RepeaterAccordionPane2.PreRender +=new EventHandler(RepeaterAccordionPane2_PreRender);
RepeaterAccordionPane2.DataBind();
int nUpdatePanelIndex = 0;
foreach (Control crInRepeater in RepeaterAccordionPane2.Controls)
{
if (crInRepeater.GetType() == typeof(RepeaterItem))
{
foreach (Control crInRepeaterItem in crInRepeater.Controls)
{
if (crInRepeaterItem.GetType() == typeof(UpdatePanel))
{
LiteralControl litTabelleBeginn = new LiteralControl("<table width=\"100%\" border=\"0\" cellspacing=\"0\" cellpadding=\"2\">");
((UpdatePanel)crInRepeaterItem).ContentTemplateContainer.Controls.Add(litTabelleBeginn);
if (dvAlleArtikel[nUpdatePanelIndex]["ArtNr1"].ToString() != "0")
{
CheckBox CheckBox1 = new CheckBox();
CheckBox1.ID = dvAlleArtikel[nUpdatePanelIndex]["ArtNr1"].ToString();
CheckBox1.Text = (dvAlleArtikel[nUpdatePanelIndex]["CheckBoxLbl1"].ToString() == "" ? "leer" : dvAlleArtikel[nUpdatePanelIndex]["CheckBoxLbl1"].ToString());
CheckBox1.AutoPostBack = true;
CheckBox1.CheckedChanged +=new EventHandler(CheckBox1_CheckedChanged);
LiteralControl litNeueTabellenZeileBeginn = new LiteralControl("<tr><td width=10><img src=\"images/helper/spacer.gif\" width=\"10\"></td><td height=\"20\">");
LiteralControl litNeueTabellenZeileEnde = new LiteralControl("</td><td width=\"100\" height=\"20\">" + dvAlleArtikel[nUpdatePanelIndex]["ArtPrice1"].ToString() + " € </td></tr>");
((UpdatePanel)crInRepeaterItem).ContentTemplateContainer.Controls.Add(litNeueTabellenZeileBeginn);
((UpdatePanel)crInRepeaterItem).ContentTemplateContainer.Controls.Add(CheckBox1);
((UpdatePanel)crInRepeaterItem).ContentTemplateContainer.Controls.Add(litNeueTabellenZeileEnde);
}
[... some other code here...]
LiteralControl litTabelleEnde = new LiteralControl("</table>");
((UpdatePanel)crInRepeaterItem).ContentTemplateContainer.Controls.Add(litTabelleEnde);
nUpdatePanelIndex++;
}
}
}
}
This code is never reached:
protected void CheckBox1_CheckedChanged(object sender, EventArgs e)
{
int foo = 0;
}
This is the CheckBox-Code generated:
<input id="AccordionPane2_content_RepeaterAccordionPane2_ctl00_6200" type="checkbox" name="AccordionPane2_content$RepeaterAccordionPane2$ctl00$6200" onclick="javascript:setTimeout('__doPostBack(\'AccordionPane2_content$RepeaterAccordionPane2$ctl00$6200\',\'\')', 0)" />
The Event is generated, but when i click the Checkbox all Content in the UpdatePanel is gone and the CheckedChanged-EventHandler is not fired.
What am i doing wrong?
Thanks to all advice, i´m really stuck.
mk
The first time the page loads you are adding all the checkboxes to the Controls collection, and they get rendered. When you do a postback (through the CheckBox's AutoPostBack) you have a check if(!IsPostBack) that doesn't allow the checkboxes to be added to the Controls collection on the postback. Because of that, you won't see the controls and the page, and when the page lifecycle tries to call the events (which occurs AFTER Page_Load), the controls that created the events are no longer there.
You will need to refactor your Page_Load method so it does two things - 1, regardless of the value of IsPostBack bind the repeaters and create the dynamic controls. 2, if IsPostBack==false, i.e., an initial load, then set the values of the dynamic controls. you don't want to set the values of the dynamic controls when IsPostBack==true because then you will lose the values the user entered.
also, just a note:
if (crInRepeater.GetType() == typeof(RepeaterItem))
can be rewritten as:
if (crInRepeater is RepeaterItem)

GridView with checkbox column. Client-side script to uncheck all except current checkbox

I am dynamically binding a typed list to a GridView control.
The Grid View Control is in an asp.net page that is wrapped in an asp:UpdatePanel (Ajax).
The first column contains a checkbox control.
Only one checkbox may be checked in this column.
If the user checks a checkbox, all other checkbox must be unchecked.
I am trying to achieve this using client-side script without success.
In the handler for the GridView’s RowDatabound event, have attempted to add an attribute to the CheckBox contained within the cell.
protected void ErrorGridView_RowDatabound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
if(e.Row.Cells[0].HasControls())
{
foreach (var control in e.Row.Cells[0].Controls)
{
if (!(control is CheckBox)) continue;
var checkBox = (CheckBox)control;
checkBox.Attributes.Add("CheckedChanged", "errorCheckChanged");
return;
}
}
}
The client side script is registered on the Page_Load event handler - as below:
if (!Page.ClientScript.IsClientScriptBlockRegistered("ErrorsCheckBoxHandler"))
Page.ClientScript.RegisterClientScriptBlock(GetType(),"ErrorsCheckBoxHandler", "function errorCheckChanged() {window.alert(\"here\"); }");
The problem is that the function is not called when any checkboxes are clicked. Hopefully someone can shed some light as to what am I missing here?
Also, what would be the best way to perform the de-selection of the any other checkboxes that are checked in the target column?
My plan would be to change the 'errorCheckChanged' function to take one parameter (the checkbox object). I would change the above code; adding to the attribute addition signature:
checkBox.Attributes.Add("CheckedChanged", "errorCheckChanged(this)");
Hopefully, I will then be able to:
(1) determine if the checkbox state is 'checked'. (If it is 'checked', then continue below steps)
(2) find the checkbox parent (= cell) and then determine the affected GridView Row.
(3) Loop through all rows setting the checkboxes to 'Checked=false' except of the current row.
Would this be considered the right approach?
Thanks
Grant
You can also add the onclick event of checkbox in design time.
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox ID="chkSelect" onclick="errorCheckChanged(this)" runat="server" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
And the JavaScript looks like
function errorCheckChanged(chkBox){
var gridView = document.getElementById('<% =GridView1.ClientID %>');
var Elements = gridView.getElementsByTagName('input');
for(var i = 0; i < Elements.length; i++){
if(Elements[i].type == 'checkbox' && Elements[i].id != chkBox.id && chkBox.checked)
Elements[i].checked = false;
}
}
use the onclick attribute rather than CheckChanged. i don't think that's a valid js event. so
checkBox.Attributes.Add("onclick", "errorCheckChanged(this);");
to get a list of checkboxes you can do
js:
var grid = document.getElementById('<% =GridView1.ClientID %>');
var checks = grid.getElementsByTagName('input');
you'll have to check the type attribute to make sure it's a checkbox, or you can give all the checkboxes a specific class to logically group them. anyway you can check your clicked element id against the list.

ASPXGridView Custom CallBack

We have the DevExpress grid and in the OnCustomCallback event we need to assign a hidden field value=true. After we need to get the hidden field value to javascript?
We tried in following manner:
protected void dgUnReconcile_CustomCallback(object sender, ASPxGridViewCustomCallbackEventArgs e)
{
ASPxGridView temp = ((DevExpress.Web.ASPxGridView.ASPxGridView)(sender));
string gridInstancename = ((DevExpress.Web.ASPxGridView.ASPxGridView)(sender)).ClientInstanceName;
if (gridInstancename.Equals("grid"))
{
List<Object> selected = dgUnReconcile.GetSelectedFieldValues(new[] { "Key" });
if (selected.Count > 0)
{
existingKey = true;//hidden field value
}
}
}
We need to access the hidden fields value through javascript
var ='<%# existingKey%>';
It always shows empty value.
Try to use the JSProperties of the grid:
aspx:
<dxwgv:ASPxGridView ID="myGridView" ClientInstanceName="myGridView" runat="server">
</dxwgv:ASPxGridView>
sets the value in code-behind (C#):
myGridView.JSProperties["cpMyValue"] = "hello, world!";
gets the value on client (js):
alert(myGridView.cpMyValue);
To change other controls during a server-side event, you might need to disable callbacks (see the ASPxGridView.EnableCallBacks property) and place both the hidden field and grid control into the UpdatePanel.
Alternatively, you can do it on the client-side with javascript if you want to keep callbacks enabled. There's a similiar sample project attached here:
http://www.devexpress.com/Support/Center/p/Q201214.aspx

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