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;
}
}