1

My controller looks as follow:

var _engine = new NopEngine();
            var categoryService = _engine.Resolve<ICategoryService>();
            var allCategory = categoryService.GetAllCategories();

            List<string> ConvertedList = new List<string>();

            for (int i = 0; i < allCategory.Count; i++)
            {
                ConvertedList.Add(allCategory[i].Name);
            }

            //fill the viewbag
            ViewBag.CategoryList = ConvertedList;

            return View("Nop.Plugin.Misc.ExportAttributes.Views.MiscExportAttributes.ExportCalculationSheet");

So basically I'm filling the ViewBag with a List of strings.

My view looks as follow:

@{
    Layout = "";
}
@using Telerik.Web.Mvc.UI;
@model ExportCalculationSheetModel
@using Nop.Plugin.Misc.ExportAttributes.Models;
@using Nop.Web.Framework;
@using Nop.Core.Domain.Catalog;
@using (Html.BeginForm())
{
    <table class="adminContent">
        <tr>
            <td colspan="2">
                <b>Filter op Categorie:</b>
            </td>
        </tr>
        <tr>
            <td class="adminTitle">
                @Html.NopLabelFor(model => model.searchCategory):
            </td>
            <td class="adminData">
                @Html.DropDownListFor(x => x.searchCategory, new SelectList(ViewBag.CategoryList, "Name"))
            </td>
        </tr>
</table>

This works, the DropDownList gets filled with the correct values. But I don't think that the ViewBag is "Best-Practice", I heard something about using a Model to select the List from, I already added a reference to the model in the view:

@model ExportCalculationSheetModel

How can I fill the list at the model class and use it in my view?

I already tried to fill the model class the following way, but that didn't work out:

public List<string> AllCategories
        {
            get
            {
                return AllCategories;
            }
            set
            {
                var _engine = new NopEngine();
                var categoryService = _engine.Resolve<ICategoryService>();
                var allCategory = categoryService.GetAllCategories();

                List<string> ConvertedList = new List<string>();

                for (int i = 0; i < allCategory.Count; i++)
                {
                    ConvertedList.Add(allCategory[i].Name);
                }
                AllCategories = ConvertedList;
            }
        }

So the two primary questions are:

  1. How do I fill the list at the model page?

  2. How do I connect the list at my model page to the dropdownlist at my view?

Thanks in advance!

4

3 回答 3

2

Change

List<string> ConvertedList = new List<string>();

to

List<SelectList> ConvertedList = new List<SelectList>();

do not need for loop . you can directly add the database return list values to ConvertedList

look this sample's Binding Data To DropDownList MVC Razor

here is a good sample

于 2013-08-14T14:32:37.770 回答
2

The only thing DropDownListFor needs is an IEnumerable<SelectListItem> (i.e., that could be a list/collection/queryable/etc.). The problem right now is that you simply have a list string instead of SelectListItem. That's easy remedied with a little LINQ-fu:

@Html.DropDownListFor(x => x.searchCategory, Model.AllCategories.Select(m => new SelectListItem { Value = m, Text = m }))

However, the better approach would be to simply have AllCategories return a list of SelectListItems off-the-bat (assuming it's only being used for populating the dropdown list).

private IEnumerable<SelectListItem> allCategories;
public IEnumerable<SelectListItem> AllCategories
{
    get
    {
        if (allCategories == null)
        {
            var _engine = new NopEngine();
            var categoryService = _engine.Resolve<ICategoryService>();

            allCategories = categoryService.GetAllCategories().Select(m =>
                new SelectListItem { Value = m.Name, Text = m.Name });
        }

        return allCategories;
    }

    // You don't need a setter
}

The first time AllCategories is accessed, the associated private variable, allCategories, will be null, so your service spins up and the list of categories is fetched. Select is used to cast the returned categories into a collection of SelectListItems. If you category has something like an Id property, you should use that for Value instead of Name. Any subsequent accesses of AllCategories will simply return the value stored in the private without hitting the database again.

Bonus Pro Tip

If you actually do need to use a for loop for something like this, you don't need to create a new list, add items to the list in the loop, and then return that list. It's easier to just use yield. For example:

public IEnumerable<int> Numbers
{
    for (int i = 0; i < 10; i++)
    {
        yield return i;
    }
}
于 2013-08-14T15:31:37.540 回答
1

May be you can try this:

Starting with a Dictionary in the Model

    public class YourOptions
    {
        public Dictionary<int, string> Option { get; set; }

        public YourOptions()
        {
            Option = new Dictionary<int, string>()
            {
                //Here you should put your code, this is an example
                { 0, "Option 1"},
                { 1, "Option 2"},
                { 2, "Option 3"},
                { 3, "Option 4"},
                { 4, "Option 5"},
                //Here you should put your code, this is an example
            };

    }

In the View

@Html.DropDownListFor(model => model.Option.Keys,
                         new SelectList(
                             Model.Option, 
                             "Key", 
                             "Value"))

Sorry for my bad english! I hope this help you!

于 2013-08-14T14:38:53.280 回答