I have a GridView
which contains a TextField
of BenefitName
(string
) and a ValueField
of BenefitInfoKeySK
(int
).
Originally I directly bound a datasource
to the combobox
and had distinct TextField
and ValueField
values. (Code Sample 2)
I updated my code to create 'cascading' comboboxes and the TextField
value no longer displays in my GridView
but it does display within the comboBox
in my edit form.
Why does the
TextField
render in my edit formcombobox
but not on myGridView
?
PartialView CodeSample 1 (Cascading combobox)
settings.Columns.Add(column =>
{
column.FieldName = "BenefitKey";
column.Name = "BenefitKey";
column.Caption = "Claim Type";
column.Width = 200;
column.Settings.AllowHeaderFilter = DefaultBoolean.False;
column.EditFormSettings.Visible = DefaultBoolean.True;
column.Settings.AllowSort = DefaultBoolean.False;
column.EditorProperties().ComboBox(p =>
{
p.CallbackRouteValues = new { Controller = "BenefitClaimDetails", Action = "GetBenefitTypes", TextField = "BenefitName", ValueField = "BenefitInfoKeySK", headerEmployeeID = Model.BenefitHeaderEmployee };
p.TextField = "BenefitName";
p.ValueField = "BenefitInfoKeySK";
p.ClientSideEvents.BeginCallback = "ClaimTypeComboBox_BeginCallback";
p.EnableCallbackMode = true;
p.Width = 200;
p.ValidationSettings.RequiredField.IsRequired = true;
p.ValidationSettings.RequiredField.ErrorText = "Claim Type cannot be blank";
p.ValidationSettings.ErrorDisplayMode = ErrorDisplayMode.ImageWithText;
});
});
PartialView Code Sample 2 (basic combobox)
settings.Columns.Add(column =>
{
column.FieldName = "BenefitKey";
column.Name = "BenefitKey";
column.Caption = "Claim Type";
column.Width = 200;
column.Settings.AllowHeaderFilter = DefaultBoolean.False;
column.EditFormSettings.Visible = DefaultBoolean.True;
column.Settings.AllowSort = DefaultBoolean.False;
column.ColumnType = MVCxGridViewColumnType.ComboBox;
var comboBoxProperties = column.PropertiesEdit as ComboBoxProperties;
comboBoxProperties.Width = 200;
comboBoxProperties.DataSource = repository.GetBenefitListByEmployee(Model.BenefitHeaderEmployee);
comboBoxProperties.TextField = "BenefitName";
comboBoxProperties.ValueField = "BenefitInfoKeySK";
comboBoxProperties.DropDownRows = 15;
comboBoxProperties.ValueType = typeof(int);
comboBoxProperties.ValidationSettings.RequiredField.IsRequired = true;
comboBoxProperties.ValidationSettings.RequiredField.ErrorText = "Claim Type cannot be blank";
comboBoxProperties.ValidationSettings.ErrorDisplayMode = ErrorDisplayMode.ImageWithText;
});
I have found that p.TextField
and p.ValueField
in code sample 1 do nothing. They can be removed with no effect on the code. However I must pass those fields in my CallBackRoute
and assign them in the controller code:
Controller Code
public ActionResult GetBenefitTypes(int claimantID, string textField, string valueField, string headerEmployeeID)
{
return GridViewExtension.GetComboBoxCallbackResult(p => {
p.TextField = textField;
p.ValueField = valueField;
p.BindList(repository.GetBenefitListByEmployee(claimantID, headerEmployeeID));
});
}
As you can see, at the end both techniques call the same Repository
method. Please let me know if I can elaborate on anything.
EDIT
I also attempted to modify Code Sample 1 by adding a columnType value and assigning a data source as shown below. This successfully displayed the TextField
on my GridView
but the null
which I pass for claimantID
prevented the Editor combobox from displaying any values. For that reason I am also including the JS
code where I assign claimantID
.
Modified PartialView Code Sample 1 (working grid view, no values in combobox)
settings.Columns.Add(column =>
{
column.FieldName = "BenefitKey";
column.Name = "BenefitKey";
column.Caption = "Claim Type";
column.Width = 200;
column.Settings.AllowHeaderFilter = DefaultBoolean.False;
column.EditFormSettings.Visible = DefaultBoolean.True;
column.Settings.AllowSort = DefaultBoolean.False;
column.EditorProperties().ComboBox(p =>
{
p.CallbackRouteValues = new { Controller = "BenefitClaimDetails", Action = "GetBenefitTypes", TextField = "BenefitName", ValueField = "BenefitInfoKeySK", headerEmployeeID = Model.BenefitHeaderEmployee };
p.TextField = "BenefitName";
p.ValueField = "BenefitInfoKeySK";
p.ClientSideEvents.BeginCallback = "ClaimTypeComboBox_BeginCallback";
p.EnableCallbackMode = true;
p.Width = 200;
p.ValidationSettings.RequiredField.IsRequired = true;
p.ValidationSettings.RequiredField.ErrorText = "Claim Type cannot be blank";
p.ValidationSettings.ErrorDisplayMode = ErrorDisplayMode.ImageWithText;
});
column.ColumnType = MVCxGridViewColumnType.ComboBox;
var comboBoxProperties = column.PropertiesEdit as ComboBoxProperties;
comboBoxProperties.DataSource = repository.GetBenefitListByEmployee(Model.BenefitHeaderEmployee, null);
comboBoxProperties.TextField = "BenefitName";
comboBoxProperties.ValueField = "BenefitInfoKeySK";
});
JS Code
@*The follwing functions handle the Cascading Benefit Type combobox*@
function OnSelectedClaimantChanged() {
BenefitClaimDetailsGridView.GetEditor("BenefitKey").PerformCallback();
}
function ClaimTypeComboBox_BeginCallback(s, e) {
e.customArgs["claimantID"] = BenefitClaimDetailsGridView.GetEditor("DependentKey").GetValue();
}
I'm sorry to include so much code and not a working project, but the Solution is quite large. I hope this will do.
I found my solution.
I started to comment out the comboBoxProperties
section line by line to understand at what point the callback would begin failing and I found that it failed due to my declaration: column.ColumnType = MVCxGridViewColumnType.ComboBox;
After looking into how the EditorProperties.Combobox()
was working I realized that in that section of code, ComboBox
was utilizing the standard MVCxColumnComboBoxProperties
rather than the DevExpress GridView ComboBox
.
I think the issue was that in the callback I was declaring the column type one way but then overriding it later on with my
comboBoxProperties
code. The change which I made was changingvar comboBoxProperties = column.PropertiesEdit as ComboBoxProperties;
to
var comboBoxProperties = column.PropertiesEdit as MVCxColumnComboBoxProperties;
The finalized working code is here. For somebody trying to put this together themselves: In order to achieve cascading comboboxes which display text but are stored with a different value you will need the following.
In your partial view give the 'initiator' column a SelectedIndexChanged
event such as this:
settings.Columns.Add(column =>
{
column.FieldName = "DependentKey";
column.Name = "DependentKey";
column.Caption = "Claimant";
column.Width = 300;
column.Settings.AllowHeaderFilter = DefaultBoolean.False;
column.EditFormSettings.Visible = DefaultBoolean.True;
column.Settings.AllowSort = DefaultBoolean.False;
column.ColumnType = MVCxGridViewColumnType.ComboBox;
var comboBoxProperties = column.PropertiesEdit as ComboBoxProperties;
/*Get an employee model for the current employee and pass that to the Depoendents method to get their list of dependents*/
comboBoxProperties.DataSource = repository.GetDependentDropdownList(repository.GetCurrentEmployee(employeeID: Model.BenefitHeaderEmployee).DimEmployee);
comboBoxProperties.TextField = "DependentName";
comboBoxProperties.ValueField = "DependentKeySK";
comboBoxProperties.DropDownRows = 15;
comboBoxProperties.ValueType = typeof(int);
comboBoxProperties.ValidationSettings.RequiredField.IsRequired = true;
comboBoxProperties.ValidationSettings.RequiredField.ErrorText = "Claimant cannot be blank";
comboBoxProperties.ValidationSettings.ErrorDisplayMode = ErrorDisplayMode.ImageWithText;
comboBoxProperties.ClientSideEvents.SelectedIndexChanged = "OnSelectedClaimantChanged";
});
In the column which is to be influenced you will need to declare it as such (this is the final version of my Code Sample 1 / Code Sample 2 from above):
settings.Columns.Add(column =>
{
column.FieldName = "BenefitKey";
column.Name = "BenefitKey";
column.Caption = "Claim Type";
column.Width = 200;
column.Settings.AllowHeaderFilter = DefaultBoolean.False;
column.EditFormSettings.Visible = DefaultBoolean.True;
column.Settings.AllowSort = DefaultBoolean.False;
column.EditorProperties().ComboBox(p =>
{ /*Populate the combobox with valid values based on the selected dependentKey*/
p.CallbackRouteValues = new { Controller = "BenefitClaimDetails", Action = "GetBenefitTypes", TextField = "BenefitName", ValueField = "BenefitInfoKeySK", headerEmployeeID = Model.BenefitHeaderEmployee };
p.ClientSideEvents.BeginCallback = "ClaimTypeComboBox_BeginCallback";
p.Width = 200;
p.ValidationSettings.RequiredField.IsRequired = true;
p.ValidationSettings.RequiredField.ErrorText = "Claim Type cannot be blank";
p.ValidationSettings.ErrorDisplayMode = ErrorDisplayMode.ImageWithText;
});
/*Display the BenefitName in the gridView. The Callback method TextField and ValueField only influence the comboBox in the Editor window*/
var comboBoxProperties = column.PropertiesEdit as MVCxColumnComboBoxProperties;
comboBoxProperties.Width = 200;
comboBoxProperties.DataSource = repository.GetBenefitListByEmployee(Model.BenefitHeaderEmployee);
comboBoxProperties.TextField = "BenefitName";
comboBoxProperties.ValueField = "BenefitInfoKeySK";
});
Create the JS
code on your Index
page - my code is above
Create the ActionResult
in your controller - my code is above
With those 4 pieces in place you can cascade the comboBoxes and properly display them in the grid as well