This appears to be a bug to me. Maybe it's not, but it's certainly changed behavior from previous releases.
If you have a RadComboBox on a Popup EditForm as part of a RadGrid, the OnLoad event seems cause problems.
Specifically, if I load the combo on the OnLoad event, the SelectedItem/SelectedIndex/SelectedValue properties are not set when the RadGrid's UpdateCommand event is fired. In addition, the RadComboBoxSelectedIndexChangedEventArgs.Value property is not set when the RadComboBox's SelectedIndexChanged event is fired.
This is a change from previous behavior. It doesn't appear to matter whether or not I set EnableLoadOnDemand or MarkFirstMatch.
The sample code below demonstrates the problem. The Popup has two RadComboBoxes, each displaying some test data. The first combo box is loaded programatically during processing of the RadGrid's ItemDataBound event, when IsInEditMode is true. The second combo box is loaded when it's OnLoad event fires. In addition, there are associated Label controls for each RadComboBox, which are set to the selected Value when the SelectedIndexChanged event fires. Finally, the RadGrid displays both of the saved items.
Forgive the length of the sample code. I did try to prune it as much as possible.
EditFormComboWithOnLoad.aspx:
EditFormComboWithOnLoad.aspx.cs:
EditFormComboWithOnLoad.aspx.designer.cs:
If you have a RadComboBox on a Popup EditForm as part of a RadGrid, the OnLoad event seems cause problems.
Specifically, if I load the combo on the OnLoad event, the SelectedItem/SelectedIndex/SelectedValue properties are not set when the RadGrid's UpdateCommand event is fired. In addition, the RadComboBoxSelectedIndexChangedEventArgs.Value property is not set when the RadComboBox's SelectedIndexChanged event is fired.
This is a change from previous behavior. It doesn't appear to matter whether or not I set EnableLoadOnDemand or MarkFirstMatch.
The sample code below demonstrates the problem. The Popup has two RadComboBoxes, each displaying some test data. The first combo box is loaded programatically during processing of the RadGrid's ItemDataBound event, when IsInEditMode is true. The second combo box is loaded when it's OnLoad event fires. In addition, there are associated Label controls for each RadComboBox, which are set to the selected Value when the SelectedIndexChanged event fires. Finally, the RadGrid displays both of the saved items.
Forgive the length of the sample code. I did try to prune it as much as possible.
EditFormComboWithOnLoad.aspx:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="EditFormComboWithOnLoad.aspx.cs" Inherits="Web.Test.EditFormComboWithOnLoad" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> <title></title></head><body> <form id="form1" runat="server"> <div> <telerik:RadScriptManager ID="radScriptManager" runat="server" EnablePartialRendering="true"> <Scripts> </Scripts> </telerik:RadScriptManager> <telerik:RadGrid ID="radGrid" runat="server" AllowPaging="True" AllowSorting="True" AutoGenerateColumns="False" GridLines="None" OnNeedDataSource="radGrid_NeedDataSource" OnItemDataBound="radGrid_ItemDataBound" OnUpdateCommand="radGrid_UpdateCommand" OnItemCommand="radGrid_ItemCommand"> <MasterTableView CommandItemDisplay="Top" AllowMultiColumnSorting="True" EditMode="PopUp" DataKeyNames="AddressId"> <RowIndicatorColumn> <HeaderStyle Width="20px"></HeaderStyle> </RowIndicatorColumn> <ExpandCollapseColumn> <HeaderStyle Width="20px"></HeaderStyle> </ExpandCollapseColumn> <Columns> <telerik:GridTemplateColumn UniqueName="country1" AllowFiltering="False" HeaderText="Address 1"> <ItemTemplate> <%# this.GetCountry1( Container.DataItem) %> </ItemTemplate> </telerik:GridTemplateColumn> <telerik:GridTemplateColumn UniqueName="country2" AllowFiltering="False" HeaderText="Address 2"> <ItemTemplate> <%# this.GetCountry2( Container.DataItem) %> </ItemTemplate> </telerik:GridTemplateColumn> <telerik:GridTemplateColumn UniqueName="editColumn" AllowFiltering="False"> <ItemTemplate> <asp:ImageButton runat="server" ID="ibEdit" SkinID="IconEdit" CommandName="Edit" /> </ItemTemplate> <HeaderStyle Width="16px" /> <ItemStyle HorizontalAlign="Center" /> </telerik:GridTemplateColumn> </Columns> <EditFormSettings EditFormType="Template"> <EditColumn UniqueName="EditCommandColumn"> </EditColumn> <PopUpSettings Modal="True" /> <FormTemplate> <asp:Panel ID="Panel1" runat="server" DefaultButton="btnSave"> <fieldset style="margin: 5px; padding: 10px;"> <table> <tr> <td> <asp:Label ID="lblCountry1" runat="server" Text="Country 1:"></asp:Label> </td> <td> <telerik:RadComboBox ID="radCountryBox1" runat="server" EnableLoadOnDemand="False" MaxHeight="200px" AutoPostBack="true" ShowWhileLoading="false" MarkFirstMatch="true" Filter="StartsWith" OnSelectedIndexChanged="radCountryBox_SelectedIndexChanged"> </telerik:RadComboBox> </td> </tr> <td> <asp:Label ID="label2" runat="server" Text="Selected Value:"></asp:Label> </td> <td> <asp:Label ID="lblSelectedValue1" runat="server"></asp:Label> </td> <tr> <tr> <td> <asp:Label ID="lblCountry2" runat="server" Text="Country 2:"></asp:Label> </td> <td> <telerik:RadComboBox ID="radCountryBox2" runat="server" EnableLoadOnDemand="False" MaxHeight="200px" AutoPostBack="true" ShowWhileLoading="false" MarkFirstMatch="true" OnLoad="CountryBox2_Load" Filter="StartsWith" OnSelectedIndexChanged="radCountryBox2_SelectedIndexChanged"> </telerik:RadComboBox> </td> </tr> <td> <asp:Label ID="label3" runat="server" Text="Selected Value:"></asp:Label> </td> <td> <asp:Label ID="lblSelectedValue2" runat="server"></asp:Label> </td> <tr> </tr> </tr> </table> </fieldset> <table width="100%" border="0" cellpadding="0" cellspacing="0" style="margin-left: 5px;"> <tr> <td align="center"> <asp:Button runat="server" ID="btnSave" CommandName="Update" Text="Save" /> <asp:Button runat="server" ID="btnCancel" CommandName="Cancel" Text="Cancel" CausesValidation="false" /> </td> </tr> </table> </asp:Panel> </FormTemplate> </EditFormSettings> </MasterTableView> </telerik:RadGrid> </div> </form></body></html>EditFormComboWithOnLoad.aspx.cs:
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;using Telerik.Web.UI;namespace Web.Test{ public partial class EditFormComboWithOnLoad : System.Web.UI.Page { #region FakeDataClasses private class Address { public int PartyId { get; set; } public int AddressId { get; set; } public int? Country1Id { get; set; } public int? Country2Id { get; set; } } private class Country { public int CountryId { get; set; } public string Name { get; set; } } #endregion private List<Country> _countries1; private List<Country> _countries2; private static List<Address> _addresses; public EditFormComboWithOnLoad() { CreateDummyCountries(); CreateDummyAddresses(); } #region SetupFakeData private void CreateDummyCountries() { _countries1 = new List<Country>(); _countries2 = new List<Country>(); AddDummyCountriesToList(_countries1); AddDummyCountriesToList(_countries2); } private void AddDummyCountriesToList(List<Country> countries) { Country country1 = new Country(); country1.CountryId = 1; country1.Name = "Country 1"; countries.Add(country1); Country country2 = new Country(); country2.CountryId = 2; country2.Name = "Country 2"; countries.Add(country2); Country country3 = new Country(); country3.CountryId = 3; country3.Name = "Country 3"; countries.Add(country3); Country country4 = new Country(); country4.CountryId = 4; country4.Name = "Country 4"; countries.Add(country4); } private void CreateDummyAddresses() { if (_addresses == null) { _addresses = new List<Address>(); Address pa = new Address(); pa = new Address(); pa.PartyId = 1; pa.AddressId = 1; pa.Country1Id = 1; pa.Country2Id = 2; _addresses.Add(pa); } } #endregion protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { } } int GetPartyId() { int partyId = 1; return partyId; } #region Grid Events protected void radGrid_NeedDataSource(object source, Telerik.Web.UI.GridNeedDataSourceEventArgs e) { radGrid.DataSource = _addresses; } protected void radGrid_ItemDataBound(object sender, Telerik.Web.UI.GridItemEventArgs e) { try { int addressId = -1; if (e.Item.IsInEditMode && e.Item is GridEditFormItem) { GridEditFormItem editedItem = (GridEditFormItem)e.Item; // load CountryBox1 from code. Us OnLoad event to load CountryBox2 RadComboBox radCountryBox1 = ((RadComboBox)editedItem.FindControl("radCountryBox1")); CountryBox_Load(radCountryBox1, null); // We only want to bind the values for edit mode only if (!(e.Item is GridEditFormInsertItem)) { object primaryKey = editedItem.GetDataKeyValue("AddressId"); if (primaryKey != null) Int32.TryParse(primaryKey.ToString(), out addressId); Address address = null; if (addressId > 0) address = _addresses.Where(item => item.AddressId == addressId).FirstOrDefault(); if (address != null) { ((RadComboBox)editedItem.FindControl("radCountryBox1")).SelectedValue = address.Country1Id.ToString(); ((RadComboBox)editedItem.FindControl("radCountryBox2")).SelectedValue = address.Country2Id.ToString(); } } } } catch (Exception ex) { e.Canceled = true; } } protected void radGrid_UpdateCommand(object source, Telerik.Web.UI.GridCommandEventArgs e) { try { int addressId = -1; Address address = null; GridEditFormItem editedItem = e.Item as GridEditFormItem; // Conditional logic depending upon if we are inserting or updating if (e.Item is GridEditFormInsertItem) { address = new Address(); address.PartyId = GetPartyId(); address.AddressId = _addresses.Max(item => item.AddressId) + 1; } else { object primaryKey = editedItem.GetDataKeyValue("AddressId"); if (primaryKey != null) Int32.TryParse(primaryKey.ToString(), out addressId); if (addressId > 0) address = _addresses.Where(item => item.AddressId == addressId).FirstOrDefault(); } if (address != null) { address.Country1Id = TextUtility.TextToNullableInt(((RadComboBox)editedItem.FindControl("radCountryBox1")).SelectedValue.ToString()); address.Country1Id = (address.Country1Id == 0 ? null : address.Country1Id); address.Country2Id = TextUtility.TextToNullableInt(((RadComboBox)editedItem.FindControl("radCountryBox2")).SelectedValue.ToString()); address.Country2Id = (address.Country2Id == 0 ? null : address.Country2Id); if (e.Item is GridEditFormInsertItem) _addresses.Add(address); } else { throw new Exception("The record no longer exists."); } } catch (Exception ex) { e.Canceled = true; } } #endregion protected void CountryBox_Load(object sender, EventArgs e) { RadComboBox radBox = sender as RadComboBox; List<Country> data = _countries1; Country none = new Country(); radBox.DataSource = data; radBox.DataTextField = "Name"; radBox.DataValueField = "CountryId"; radBox.EmptyMessage = "Select a Country"; radBox.DataBind(); } protected void CountryBox2_Load(object sender, EventArgs e) { RadComboBox radBox = sender as RadComboBox; List<Country> data = _countries2; Country none = new Country(); radBox.DataSource = data; radBox.DataTextField = "Name"; radBox.DataValueField = "CountryId"; radBox.EmptyMessage = "Select a Country"; radBox.DataBind(); } protected void radCountryBox_SelectedIndexChanged(object o, RadComboBoxSelectedIndexChangedEventArgs e) { int countryid; Int32.TryParse(e.Value, out countryid); Label lbl = (o as RadComboBox).Parent.FindControl("lblSelectedValue1") as Label; lbl.Text = countryid.ToString(); } protected void radCountryBox2_SelectedIndexChanged(object o, RadComboBoxSelectedIndexChangedEventArgs e) { int countryid; Int32.TryParse(e.Value, out countryid); Label lbl = (o as RadComboBox).Parent.FindControl("lblSelectedValue2") as Label; lbl.Text = countryid.ToString(); } protected void radGrid_ItemCommand(object source, GridCommandEventArgs e) { if (e.CommandName.Equals(RadGrid.InitInsertCommandName)) { radGrid.MasterTableView.EditFormSettings.CaptionFormatString = "Adding new Address for Party"; } else if (e.CommandName.Equals(RadGrid.EditCommandName)) { radGrid.MasterTableView.EditFormSettings.CaptionFormatString = "Editing Address for Party"; } } protected string GetCountry1(object source) { // handle null object if (source == null) return "(null)"; string returnValue = string.Empty; Address item = (Address)source; if (item.Country1Id != null) returnValue = TextUtility.PruneText(_countries1.Where(countryItem => countryItem.CountryId == item.Country1Id).First().Name); else returnValue += "(null)"; return returnValue; } protected string GetCountry2(object source) { // handle null object if (source == null) return "(null)"; string returnValue = string.Empty; Address item = (Address)source; if (item.Country2Id != null) returnValue = TextUtility.PruneText(_countries2.Where(countryItem => countryItem.CountryId == item.Country2Id).First().Name); else returnValue += "(null)"; return returnValue; } public class TextUtility { public static string PruneText(string text) { return text; } public static int? TextToNullableInt(string text) { int value; if (int.TryParse(text, out value)) return value; else return (int?)null; } } } }EditFormComboWithOnLoad.aspx.designer.cs:
//------------------------------------------------------------------------------// <auto-generated>// This code was generated by a tool.//// Changes to this file may cause incorrect behavior and will be lost if// the code is regenerated. // </auto-generated>//------------------------------------------------------------------------------namespace Web.Test { public partial class EditFormComboWithOnLoad { /// <summary> /// form1 control. /// </summary> /// <remarks> /// Auto-generated field. /// To modify move field declaration from designer file to code-behind file. /// </remarks> protected global::System.Web.UI.HtmlControls.HtmlForm form1; /// <summary> /// radScriptManager control. /// </summary> /// <remarks> /// Auto-generated field. /// To modify move field declaration from designer file to code-behind file. /// </remarks> protected global::Telerik.Web.UI.RadScriptManager radScriptManager; /// <summary> /// radGrid control. /// </summary> /// <remarks> /// Auto-generated field. /// To modify move field declaration from designer file to code-behind file. /// </remarks> protected global::Telerik.Web.UI.RadGrid radGrid; }}