質問

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

役に立ちましたか?

解決

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 }))

他のヒント

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>

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;}
    }
@Html.DropDownListFor(
     m => m.Country, 
          new SelectList(_CountryList, "CountryID", "Title"),
          new { @class = "form-control" }
)

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)
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top