Reputation: 1
I have the following Action method, which have a viewBag with a list of strings:-
public ActionResult Login(string returnUrl)
{
List<string> domains = new List<string>();
domains.Add("DomainA");
ViewBag.ReturnUrl = returnUrl;
ViewBag.Domains = domains;
return View();
}
and on the view i am trying to build a drop-down list that shows the viewBag strings as follow:-
@Html.DropDownList("domains",(SelectList)ViewBag.domains )
But i got the following error :-
Cannot convert type 'System.Collections.Generic.List' to 'System.Web.Mvc.SelectList'
So can anyone adive why i can not populate my DropDown list of a list of stings ? Thanks
Upvotes: 21
Views: 67089
Reputation: 7537
You really need to have a "key", or index, for each value, because you have to convert each name to an IEnumerable<SelectListItem>
, which requires an ID value and a Text string to display. You could do that using one of two ways:
Use a Dictionary
Make a Dictionary<int, string>
:
Dictionary<int, string> domainDict = new Dictionary<int, string>();
and everytime you add a domain, you add a number:
domainDict.Add(1, "DomainA");
If you have a source list for this information with multiple domains, you could do a foreach
on that list and use an indexer variable similar to what I show, below, instead of manually adding the items.
You will need a model. Create a class called DomainViewModel.cs
and add this inside:
public class DomainViewModel()
{
public int Id { get; set; }
public string Name { get; set; }
}
Then iterate over your dictionary to add the items to a DomainViewModel
, and then add each of those items to a List<DomainViewModel>
, similar to what I have below in the next section, except it would look like this:
List<DomainViewModel> lstDomainModel = new List<DomainViewModel>();
foreach(KeyValuePair<int, string> kvp in domainDict)
{
DomainViewModel d = new DomainViewModel();
d.Id = kvp.Key; // number
d.Name = kvp.Value; // domain name
lstDomainModel.Add(d);
}
(Skip to Finishing Up, below)
List iteration with loop indexer
If you don't want to use a Dictionary<>
, you could just add the index on the fly by iterating the List<string>
and putting it into a List<DomainViewModel>
directly. Here's how you would do that:
1) Ensure you have created the DomainViewModel.cs
class from above.
2) Edit your controller function to build your List<string>
, then iterate over it to add it in chunks of DomainViewModel
to a new List<DomainViewModel>
using an indexer variable (idx
):
List<string> domains = new List<string>();
domains.Add("DomainA"); // etc.
List<DomainViewModel> lstDomainModel = new List<lstDomainModel>();
int idx = 0;
// Add your List<string> to your List<DomainViewModel>
foreach (string s in domainList)
{
DomainViewModel domainModel = new DomainViewModel();
domainModel.Id = idx;
domainModel.Name = s;
lstDomainModel.Add(domainModel);
idx++;
}
Finishing Up
Using either method, once you have it in a List<DomainViewModel>
, you could do:
IEnumerable<SimpleListItem> domainList =
lstDomainModel.Select(d => new SelectListItem {
Text = d.Name,
Value = d.Id.ToString()
}
);
ViewBag.Domains = domainList;
And show it in your view like this:
@Html.DropDownList("Domains", (IEnumerable<SelectListItem>)ViewBag.Domains)
Upvotes: 0
Reputation: 1547
ViewBag is not strongly typed. You can use ViewModel classes to pass instances to view so that view can utilize more than one data source.
public ActionResult Login(string returnUrl)
{
List<string> domains = new List<string>();
domains.Add("DomainA");
ViewModel model=new ViewModel();
model.ReturnUrl = returnUrl;
model.Domains =new SelectList(domains);
return View(model);
}
Public Class ViewModel()
{
property Url ReturnUrl{get;set;}
property SelectList Domains{get;set;}
}
Upvotes: 4
Reputation: 27
@Html.DropDownListFor(
m => m.Country,
new SelectList(_CountryList, "CountryID", "Title"),
new { @class = "form-control" }
)
Upvotes: 0
Reputation: 239300
Because DropDownList
does not accept a list of strings. It accepts IEnumerable<SelectListItem>
. It's your responsibility to convert your list of strings into that. This is easy enough though:
domains.Select(m => new SelectListItem { Text = m, Value = m })
Then, you can feed that to DropDownList
:
@Html.DropDownList("domains", ((List<string>)ViewBag.domains).Select(m => new SelectListItem { Text = m, Value = m }))
Upvotes: 34
Reputation: 6832
To complete Chris Pratt's answer, here's some sample code to create the dropdown :
@Html.DropDownList("domains", new SelectList(((List<string>)ViewBag.domains).Select(d => new SelectListItem { Text = d, Value = d }), "Value", "Text"))
Which will produce the following markup :
<select id="domains" name="domains">
<option value="item 1">item 1</option>
<option value="item 2">item 2</option>
<option value="item 3">item 3</option>
</select>
Upvotes: 5