Model Binding is not happening with DropDownList - c#

Here is the link to MVC dotnetfiddle: https://dotnetfiddle.net/k1E6nG
I have a property called as "Result" in my ViewModel which is a List.
Output is an table which can dynamically add rows & each row is an combination of different inputs( like Dropdown & Text Box).
Controller:
rows.Add(new Row() { SQ1 = "2", SQ2 = "Arun", SQ3 = "kumar" });
I am assigning Values to individual Row. In the output, I can see the values getting populated in Text Boxes( Arun & kumar) whereas the DropDown list is not showing the selected value i.e DropDownList in 1st Row should show Benz as selected value

Add an additional parameter to your select list, like this:
<td> #Html.DropDownListFor(model => model.Result[i].SQ1, new SelectList(Model.DDlist,"Value", "Text", Model.Result[i].SQ1)) </td>
Select list takes an optional argument for the selected value, so you can set your selected value there.

Related

Get selected item of DropDownListFor and using it to create new list

Have some problems trying to solve this. Have two DropDownListFor where the first is populated with data and the second should be populated using the selected value from the first.
Lets say the first DropDownlist contains these data:
RoutesList;
Value = "CoOs", Text = "Copenhagen - Oslo",
Value = "StOs", Text = "Stockholm - Oslo",
Value = "OsCo", Text = "Oslo - Copenhagen"
In my razor view I'm trying to create a new list based on the selected value.
How do I get the selected value, lets say "StOs" and format it so it only contains the first two letters "St"? Trying to do this with C# and not Jquery.
My code
// Loads RoutesList to departureRouteSelectList
var departureRouteSelectList = Model.RoutesList;
// Finds selected value
var selectedItem = departureRouteSelectList.Select(x => x.Value);
// Create new selectList for returnRoute
List<SelectListItem> returnRouteSelectList = null;
I'm not sure if the "Select" command does what I want and getting the "StOs"?
Understanding what you want make me think this post will resolve your problem:
Can't get my DropDownListFor to select a selected SelectListItem item in a Dropdown menu

How can I make dropdownlistfor selected value persist after submit

The following block of code is used to make the selected value of a dropdownlistfor persist after submit:
#Html.DropDownListFor(x => Model.Value, new SelectList(Model.Values, #Model.Value))
In this block of code, Model.Values is a list of strings and the #Model.Value specifies which value is selected.
This block of code works great but I'm trying to do the same thing with a list of SelectListItems (rather than a list of strings). In the following code Model.Values is a list of SelectListItems.
#Html.DropDownListFor(x => Model.Value, Model.Values, Model.Value,
new
{
id = "ValueDD", onchange = "this.form.submit()"
})
Is it possible to use #Model.Value as I did in the first code block to set the selected value?
SelectListItem has a property Selected that needs to be set for the selected item, see http://msdn.microsoft.com/en-us/library/system.web.mvc.selectlistitem.ASPX
So in your controler you can just set the Selected property of the item that needs to be selected, assuming you are using the controler to build the list of Model.Values

Binding custom property updates to the datasource abnormally?

At first, I want to talk a little about normal binding (with standard property such as Text of a textbox). The sample grid here has only 2 rows (for simplicity). Suppose I have a table of 2 rows (myDataTable) with 2 columns (ID and Name), a DataGridView (myGrid) and a TextBox (myTextBox). Here is the code for binding data:
myGrid.DataSource = myDataTable;
myTextBox.DataBindings.Add("Text", myDataTable, "Name");
After binding data, when the selection changes in the grid, the info is updated automatically to the control TextBox, for example, the 2 rows are:
ID | Name
1 .NET
2 Java
At first, the selection in grid is at index 0, the Text of myTextBox is ".NET", moving the selection to next position (at index 1), the Text of myTextBox is "Java", moving again and again, forward and backward, it works OK as I expect. But now I have a control with a custom property called List, this is type of List and is readonly. I want to bind it to a column of table (for example, Name), I do the same binding rule, however add a little custom Parse to format the correct string before updating to the datasource (myDataTable) because my custom property is type of List while my Name column is type of string, here is the binding code:
Binding bind = new Binding("List", myDataTable, "Name"){
ControlUpdateMode = ControlUpdateMode.Never //Because my List property is readonly
};
//formating string data before updating to the datasource
bind.Parse += (s,e) => {
List<string> data = (List<string>) e.Value;
if(data.Count == 0) e.Value = DBNull.Value;
else e.Value = string.Join(",",data.ToArray());//format as comma separated string
};
myCustomControl.DataBindings.Add(bind);
In this case, suppose myDataTable currently has no data at column Name like this:
ID | Name
1 <DBNull.Value> <--- current index
2 <DBNull.Value>
After running the demo, the current selection index in the grid is 0, I try changing the value of myCustomControl property List (the Items, not the reference), for example, update it like this:
myCustomControl.List.Add(".NET");
myCustomControl.List.Add("Java");
Then, moving the selection in grid to the next position (index 1), the value ".NET,Java" is updated to the datasource in row 0 at column Name, like this:
ID | Name
1 .NET,Java
2 <----- current index
Now if I move the selection back to index 0, the value at column Name in row 1 is also updated to ".NET,Java" like this:
ID | Name
1 .NET,Java <----- current index
2 .NET,Java
Which is not what I want. I mean the value should be updated via control myCustomControl. Here is what I want:
ID | Name
1 .NET,Java <----- current index
2
I can understand that, at the time moving back from index 1 to index 0, the value of List property is still a List with 2 items (".NET" and "Java") and so after the moving, this is updated to the cell at column Name in row 1. I'm finding how to reset that value of List property after it's updated to the cell at column Name in row 0 so that when the selection is at index 1, it's already empty. I'v tried changing the Parse event handler to the following but no good shake:
bind.Parse += (s,e) => {
List<string> data = (List<string>) e.Value;
if(data.Count == 0) e.Value = DBNull.Value;
else e.Value = string.Join(",",data.ToArray());//format as comma separated string
//I think at here, the value has been already updated to the datasource
//and I can perform the reset
myCustomControl.List.Clear();
};
But it seems to Clear before the value is updated to the datasource and so there is no value udpated to the datasource (instead of ".NET,Java", it's a DBNull.Value).
Then I have also tried this:
bind.BindingComplete += (s,e) => {
if(e.BindingCompleteContext == BindingCompleteContext.DataSourceUpdate)
myCustomControl.List.Clear();
};
I thought, it should check if the data is updated to the datasource, the List can be clear. I have also tried some flag to mark as true before clearing and reset it to false after clearing, use this flag to control the flowing in bind.Parse but it did nothing.
Do you have any idea to solve this problem? Your help would be highly appreciated! Thank you.
I've found the solution myself. In fact I can't reset the List anyway, this will update the underlying datasource when switching between rows in the grid. The key idea here is initially set DataSourceUpdateMode to DataSourceUpdateMode.Never, then whenever the List is about to change, turn the DataSourceUpdateMode to DataSourceUpdateMode.OnPropertyChanged. In the Parse event handler, after the parsing is done, reset DataSourceUpdateMode to DataSourceUpdateMode.Never. And that works greatly. The underlying datasource is updated only when user changing the control's value (List) by typing or selecting ,...
Here is all the code:
Binding bind = new Binding("List", myDataTable, "Name"){
ControlUpdateMode = ControlUpdateMode.Never, //Because my List property is readonly
DataSourceUpdateMode = DataSourceUpdateMode.Never//This will be turned on when preparing to change the List's value
};
//formating string data before updating to the datasource
bind.Parse += (s,e) => {
List<string> data = (List<string>) e.Value;
if(data.Count == 0) e.Value = DBNull.Value;
else e.Value = string.Join(",",data.ToArray());//format as comma separated string
//At here reset the DataSourceUpdateMode to Never
//We can also do this in BindingComplete event handler with BindingCompleteContext = BindingCompleteContext.DataSourceUpdate
myCustomControl.DataBindings[0].DataSourceUpdateMode = DataSourceUpdateMode.Never;
};
myCustomControl.DataBindings.Add(bind);
myCustomControl has a method to update/populate the new items for the List property called UpdateList(), we have to set DataSourceUpdateMode to OnPropetyChanged at the very beginning of the method like this:
public void UpdateList(){
if(DataBindings.Count > 0) DataBindings[0].DataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged;
//The remaining code for populating/updating new items goes below
....
}
And that's all, very clean. Hope this will help someone who will encounter the same situation with me.Thank you!

SelectList with a null selection

I have a bunch of drop down lists in my view, such as this one:
#Html.DropDownListFor(model => model.Process, Model.ProcessList)
They all take in a SelectList based on data from a database table like this:
ProcessList = new SelectList(_db.Processes, "ID", "Name");
where _db.Processes returns a ObjectSet<Process>.
The issue I have is that sometimes the property that is set by the drop down list can be no selection, i.e. null. How can I add a null selection to the SelectList>
#Html.DropDownListFor(model => model.Process, Model.ProcessList,"--Select Process--")
The above line would add --select process-- at the top of select list and if this value is selected, empty string will be posted and bound property will be set to null (Process in this case)

SelectedItem not being remembered in SelectList in ASPNET.MVC

I have the following code which is meant to populate a dropdown with a bunch of integer values and make the currently selected value (in this case, 13) be the selected item.
I've used the same technique but for string values and it works great, remembering each time when I get to the view what the current value is.
In controller:
var x = new[] { 1, 2,3,4,5,6,7,8,9,10,11,12,13,14,15 };
ViewData["Field"] = new SelectList(x, 13);
In view:
<%=Html.DropDownList("Field", (IEnumerable<SelectListItem>)ViewData["Field"])%>
When I debug and watch the ViewData["Field"] object, it does have a selectedValue of 13 and so it must be reaching the View but getting ignored there as all I see on the page is a dropdown with the values 1 to 15, but with 1 showing (none selected so shows the first one)
Is this a bug or am I doing something really stupid?
Thanks
Graeme
I seem to recall that it doesn't actually use the Selected property of the SelectList element. I usually have one ViewData item be the select list and another be the selected value.
Controller:
var x = new[] { 1, 2,3,4,5,6,7,8,9,10,11,12,13,14,15 };
ViewData["Fields"] = new SelectList(x);
ViewData["Field"] = 13;
View
<%= Html.DropDownList("Field", (IEnumerable<SelectListItem>)ViewData["Fields"] ) %>
This was happening to me! I was pulling my hair out for hours, but I eventually figured it out. In my case I was creating a drop-down list like this:
<%= Html.DropDownList("bookId", Model.ProductMenu, new { onchange = "goToBook();" })%>
And it was not printing the selected option. But the dropdown right next to it was working fine:
<%= Html.DropDownList("segmentIndex", Model.SegmentMenu, new { onchange = "goToSegment();" })%>
They were being generated the exact same way in the controller, and the debugger would always show the properly selected value as the view was returned. So what the heck?
The difference was in the view itself. "bookId" in my app happens to be a route/querystring value and segmentIndex is not. Simply changing the name "bookId" in the view to "bookIdBLAH" fixed it!

Categories

Resources