Peter
Peter

Reputation: 233

ASP.Net MVC DropDownList EditorTemlate

I create a DropDownList EditorTemlate which works fine while I pass a ViewBag to the EditorTemlate (I already tied that to a view model). Below is my code snippet. DropDownList:

      @model dynamic
       @{
          Layout = "~/Views/Shared/EditorTemplates/_Layout.cshtml";
        }

       @Html.DropDownList("", (SelectList) ViewBag.DropDownList,"Select an option")

Register View Model:

 public class RegisterModel
 {
   [Required]
    [DataType(DataType.Password)]
    [Display(Name = "Confirm Password", Prompt = "Confirm Password")]
    [Compare("Password", ErrorMessage = "The Password and Confirmation Password do not match")]
    public string ConfirmPassword { get; set; }

    [Required]
    [Display(Name = "Question", Prompt = "Question")]
    public string Question { get; set; }

    [Required]
    [Display(Name = "Answer",Prompt="Answer")]
    public string Answer { get; set; }

    [Required]
    [UIHint("DropDownList")]
    [Display(Name = "User Role", Prompt = "User Role")]
    public IEnumerable<UserRoles> RoleId { get; set; }
   }

     My Controller:

    [HttpGet]
    public ActionResult Users() {
        var DropDownListModel = (from mm in db.roles
                      orderby mm.RoleName
                      select mm).ToList();

        ViewBag.DropDownList = new SelectList(DropDownListModel, "RoleId", "RoleName");

        ViewBag.Content = from users in db.UserDetails
                          select users;
        return View();
    }

Update

My View

    @using (Html.BeginForm())
     { 
      @Html.AntiForgeryToken()
      @Html.EditorForModel()

      <input type="submit" value="Create User" />
      Html.EndForm();
     }

End Update

My challenge is the fact that this is tied to a single model. Is their anyway I can make my DropDownList EditorTemplate accept a model dynamically (a general purpose DropDownList EditorTemplate, regardless of the items) so that I'll use the same dropdownlist for all User Role listings, products listings, Module listings,... ? I've been stuck for 2 days on this. All search seems to be tied to a model at design time.

More on Update Assuming you have other models you want to present within the same, or other views as dropdownlist, the idea is to create a single EditorTemplate that could accept model as parameter and present a dropdownlist based on the model passed to it. I don't want to create EditorTemplate for every view presenting different models. Keep in mind that I am using @Html.EditorForModel() to display the entire form.

So sorry guy, I guess I am too used webforms where I can do this simply. I'm still very new to MVC.

Upvotes: 0

Views: 740

Answers (2)

Erik Funkenbusch
Erik Funkenbusch

Reputation: 93434

You don't really seem to understand how an editor template really works, or more importantly, you don't really seem to understand the issues around what it is you're asking for.

First, you have to consider that an a DropDownList is two things. 1) A list of items. and 2) A property that will hold the selected value from that list of items.

Because an EditorTemplate can only apply to one property in a model, how exactly are you supposed to make it apply to two items? The answer is that you can't, at least not without some kind of protocol or pattern in place.

Your problem is that you're trying to apply the Editor Template to the wrong thing in a DropDownList is the SelectedValue, not the List of items.

What you need to do is something like this:

public class RegisterModel
{
    [Required]
    [UIHint("DDL")]
    [Display(Name = "User Role", Prompt = "User Role")]
    public int? RoleId { get; set; }  // important that this is nullable

    [Required]
    [UIHint("DDL")]
    [Display(Name = "User Role 2", Prompt = "User Role 2")]
    public int? RoleId2 { get; set; }  // important that this is nullable


    public IEnumerable<SelectListItem> UserRoles { get; set; }
}

In your controller:

public ActionResult Index()
{
    var DropDownListModel = 
        (from mm in db.roles 
         orderby mm.RoleName
         select new SelectListItem { Text = mn.RoleName, Value = mn.RoleId })
         .ToList();

    return View(new RegisterModel { UserRoles = DropDownListModel });

}

In EditorTemplates\DDL.cshtml

@model int

@Html.DropDownListFor(x => x, ViewBag.DDLItems, ViewBag.DDLUnselectedValue)

Then, in your view, you do this:

@model RegisterModel
...

<p> A Role ID </p>
@Html.EditorFor(x => x.RoleId, 
       new { DDLItems = Model.UserRoles, DDLUnselectedValue = "Select A Value..." })

<p> A Second Role ID </p>
@Html.EditorFor(x => x.RoleId2, 
       new { DDLItems = Model.UserRoles, DDLUnselectedValue = "Select A Value 2..." })

The important things to note here are this:

Because you're utilizing the "additionalViewData" field of EditorFor, this data is not present in the general ViewData/ViewBag dictionaries, only in the one the Editor Template sees. So you can pass separate variables to each instance of your Editor Template.

Use strongly typed DropDownListFor, it will save you a lot of headache. Use a nullable Selected Id field, this helps with validation and makes it much easier to know when a value has not been selected (the Requred attribute enforces that it's set if you check ModelState.IsValid on postback)

Set the EditorTemplate on the Selected value, not on the DropDown list of values, since this is the "type" of the EditorTemplate.

Don't bother with SelectList, just use a collection of SelectListItems, it works a lot better.

Now, having done all this.. it's really not saving you much work... Notice that it basically looks a lot like the standard Html helper DropDownListFor... unless your editor template is going to have a lot more stuff in it...

Upvotes: 2

user3842306
user3842306

Reputation: 56

//Partial View

@{
List<SelectListItem> DataItems = new List<SelectListItem>();
using(var db = new ModelEntites()){
 foreach(var _Item in db.Table.ToList())
{
DataItems.add(_Item.Valriables);
}
ViewBag.PublicName = DataItems;
}
@HtmlDropDownList("PublicName");
}

Upvotes: 0

Related Questions