3

I have view in which it loop through the model and display the details in editable mode. One of the model value is from a select list like below

@if (Model != null)
    {
    for (int i = 0; i < Model.provider_service_dtls.Count; i++)
     {
    <tr>
    <td> @Html.DropDownListFor(m => m.provider_service_dtls[i].activity_code_type,
 (SelectList)@ViewBag.activity_code_type, "--- Select Activity Code Type ---", new { @class = "m-wrap" })</td>
    <td>@Html.TextBoxFor(m => m.provider_service_dtls[i].activity_name)</td>    
    </tr>

    }
    } 

Here the ViewBag.activity_code_type contain the values Internal & Standard when submitting if user selected Internal its value 1 will pass to controller and if Standard it will be 2 and here the default value will be "--- Select Activity Code Type ---"

enter image description here

Now when i open the same request in edit mode if the model value for provider_service_dtls[i].activity_code_type is 1 the select list should be default select as Internal and Standard if it is 2.

I coded like this

    @Html.DropDownListFor(m => m.provider_service_dtls[i].activity_code_type,
 (SelectList)@ViewBag.activity_code_type, Model.provider_service_dtls[i].activity_code_type)

But it is not working as expected it is giving the result as below picture

enter image description here

Here it should default selected Internal. What is the change to do achieve the same?

Edited

Model

public partial class provider_service_dtls
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public long service_id { get; set; }

        public long preapproval_id { get; set; }

        public string activity_code_type { get; set; }
        public string activity_type { get; set; }

        public string activity_type_name { get; set; }


        public string activity_code { get; set; }
        public string activity_name { get; set; }
        public string internal_activity_code { get; set; }
        public string internal_activity_name { get; set; }


        [ForeignKey("preapproval_id"), InverseProperty("provider_service_dtls")]
        public virtual provider_preapproval preapproval { get; set; }


    }

Editor template

@model Provider.Models.provider_preapproval
@Html.DropDownListFor(m => m.activity_code_type, (SelectList)ViewData["options"])

View

Inside the for loop i coded like this

  @Html.EditorFor(m => m.provider_service_dtls,
new { options = (SelectList)@ViewBag.activity_code_type })

I am getting an error

'System.Web.Mvc.HtmlHelper' does not contain a definition for 'EditorFor' and the best extension method overload 'System.Web.Mvc.Html.EditorExtensions.EditorFor(System.Web.Mvc.HtmlHelper, System.Linq.Expressions.Expression>, string, object)' has some invalid arguments

Tieson T.
  • 20,774
  • 6
  • 77
  • 92
Sachu
  • 7,555
  • 7
  • 55
  • 94

2 Answers2

2

Unfortunately @Html.DropDownListFor() behaves a little differently than other helpers when rendering controls in a loop. This has been previously reported as an issue on CodePlex (not sure if its a bug or just a limitation)

Create a custom EditorTemplate for the type in the collection.

In /Views/Shared/EditorTemplates/provider_service_dtls.cshtml (note the name must match the name of the type)

@model yourAssembly.provider_service_dtls

@Html.HiddenFor(m => m.service_id)
@Html.DropDownListFor(m => m.activity_code_type, (SelectList)ViewData["options"], "--- Select Activity Code Type ---")
.... // html helpers for other properties of provider_service_dtls

and then in the main view, pass the SelectList to the EditorTemplate as additionalViewData

@model yourAssembly.provider_preapproval 

@using (Html.BeginForm())
{
  .... // html helpers for other properties of provider_preapproval

  @Html.EditorFor(m => m.provider_service_dtls, new { options = (SelectList)@ViewBag.activity_code_type })
  ...

The EditorFor() methods accepts IEnumerable<T> and will generate the controls for each item in the collection

Edit

An alternative is to create a new SelectList in each iteration of the for loop, where you need to set the Selected property of SelectList. This means that your ViewBag property must be IEnumerable<T>, not a SelectList, for example in the controller

ViewBag.ActivityCodeTypeList = new[]
{
  new { ID = 1, Name = "Internal" },
  new { ID = 2, Name = "Standard" }
}

and in the view

for (int i = 0; i < Model.provider_service_dtls.Count; i++)
{
  @Html.DropDownListFor(m => m => m.provider_service_dtls[i].activity_code_type,
    new SelectList(ViewBag.ActivityCodeTypeList, "ID", "Name", Model.provider_service_dtls[i].activity_code_type),
    "--- Select Activity Code Type ---")
}
  • so i cannot use this inside forloop? – Sachu Jul 02 '15 at 01:41
  • Well there is another option, but it means that you need to construct a new `SelectList` in each iteration (not very efficient). Its also the only way it will work if you were to use `ListBoxFor()` so I suggest you use an `EditorTemplate` which is a far better approach. Not to mention you now have a reusable control so anywhere else in you app that you need to generate controls for the type, you can just use `@Html.EditorFor()` –  Jul 02 '15 at 01:46
  • Also your use of `@Html.DropDownListFor()` in the last code snippet is wrong. The 3rd parameter is for generating an `optionLabel` (i.e. the `"--- Select Activity Code Type ---"` you used previously) which is why your second image shows `"1"` as the first option –  Jul 02 '15 at 01:49
  • I'm confused. Does typeof `provider_preapproval` contain a property named `activity_code_type`? - because the parent `provider_service_dtls` also has a property named `activity_code_type`? My best guess is that the template should be `provider_service_dtls.cshtml` and in the main view assuming its `@model IEnumerable` then its just `@Html.EditorFor(m => m, new { options = (SelectList)@ViewBag.activity_code_type })` –  Jul 02 '15 at 02:00
  • And please, you really need to start using normal conventions for naming your classes and property names :) –  Jul 02 '15 at 02:01
  • @stepehmuecke `provider_preapproval` doesn't have property names `activity_code_type` it is only in `provider_service_dtls` but a `provider_preapproval` can contain multiple `provider_service_dtls` and my main view is `@model Provider.Models.provider_preapproval` – Sachu Jul 02 '15 at 02:07
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/82147/discussion-between-sachu-and-stephen-muecke). – Sachu Jul 02 '15 at 02:07
0

Simply you can try this by using IEnumerable Model type list like

 @Html.DropDownList("ReceiverID", (IEnumerable<SelectListItem>)(m => m.activity_code_type), "--- Select ---", new { @class ="form-control" }) 

Hope it will work

Ananda G
  • 2,389
  • 23
  • 39