Asp.Net MVC3 - Как создать динамический DropDownList

Я нашел много статей об этом, но все же я не знаю, как именно это сделать. Я пытаюсь создать свой собственный движок блога, у меня есть View for create article (сначала я использую EF и Code), и теперь я должен заполнить число категорий, в которые должна быть добавлена ​​статья, но я хочу изменить его в раскрывающемся списке с именами категории. Моя модель выглядит так:

public class Article
{
    public int ArticleID { get; set; }
    [Required]
    public string Title { get; set; }
    [Required]
    public int CategoryID { get; set; }
    public DateTime Date { get; set; }
    [Required()]
    [DataType(DataType.MultilineText)]
    [AllowHtml]
    public string Text { get; set; }
    public virtual Category Category { get; set; }
    public IEnumerable<SelectListItem> Categories { get; set; }
    public virtual ICollection<Comment> Comments { get; set; }
}
public class Category
{
    public int CategoryID { get; set; }
    [Required]
    public string Name { get; set; }
    public virtual ICollection<Article> Articles { get; set; }

}

Я знаю, что должен использовать Enum (или я думаю), но я точно не знаю, как это сделать. Я не знаю, какой учебник из того, что я нашел, лучше для меня.


Edit:

Спасибо за ваши ответы, но я нашел что-то еще. Я пробую это:

Это моя модель:

public class Article
{
    [Key]
    public int ArticleID { get; set; }

    [Display(Name = "Title")]
    [StringLength(30, MinimumLength = 5)]
    [Required]
    public string Title { get; set; }

    public DateTime Date { get; set; }

    public int CategoryID { get; set; }

    [Required()]
    [DataType(DataType.MultilineText)]
    [AllowHtml]
    public string Text { get; set; }

   public Category Category { get; set; }

    public virtual ICollection<Comment> Comments { get; set; }

    public IEnumerable<Category> Categories { get; set; }
}
public class Category
{
[Key]
    public int CategoryId { get; set; }
    [Required]
public string CategoryName { get; set; }
    public virtual ICollection<Article> Articles { get; set; }

}

Это мой контроллер для создания статьи:

public ActionResult Vytvorit()
{
    IEnumerable<Category> categories = GetCaregories();
    var view = View(new Article() { Categories = categories });
    view.TempData.Add("Action", "Create");

    return view;

}

private static IEnumerable<Category> GetCaregories()
{
    IEnumerable<Category> categories;
    using (BlogDBContext context = new BlogDBContext())
    {
        categories = (from one in context.Categories
                      orderby one.CategoryName
                      select one).ToList();
    }
    return categories;
}

private Category GetCategory(int categoryID)
{
        return db.Categories.Find(categoryID);
}
//
// POST: /Clanky/Vytvorit

[HttpPost]
public ActionResult Vytvorit(Article newArticle)
{

    try
    {
        if (newArticle.CategoryID > 0)
        {
            newArticle.Category = GetCategory(newArticle.CategoryID);
        }
        if (TryValidateModel(newArticle))
        {
                db.Articles.Add(newArticle);
                db.SaveChanges();
            return RedirectToAction("Index");
        }
        else
        {
            newArticle.Categories = GetCaregories();
            var view = View(newArticle);
            view.TempData.Add("Action", "Create");
            return view;
        }
    }
    catch
    {
        return View();

    }
}

И это часть моего взгляда:

     @Html.DropDownListFor(model => model.CategoryID, new SelectList(Model.Categories,"CategoryID","CategoryName"))
        @Html.ValidationMessageFor(model => model.CategoryID)

У меня проблема с NullReferenceExeption, но я не знаю почему. Могу ли я это сделать так? Мне это очень легко.

Ответ 1

Ваша модель кажется довольно странной. Он содержит такие свойства, как CategoryID и Category, которые кажутся избыточными. Он также содержит свойство коллекции SelectListItem, называемое Categories. Итак, это модель или модель представления? Это выглядит довольно запутанным. Пусть это модель. В этом случае, скорее всего, будет выглядеть примерно так:

public class Article
{
    public int ArticleID { get; set; }

    [Required]
    public string Title { get; set; }

    public DateTime Date { get; set; }

    [Required()]
    [DataType(DataType.MultilineText)]
    [AllowHtml]
    public string Text { get; set; }

    public virtual Category Category { get; set; }

    public IEnumerable<Category> Categories { get; set; }

    public virtual ICollection<Comment> Comments { get; set; }
}

public class Category
{
    public int CategoryID { get; set; }

    [Required]
    public string Name { get; set; }

    public virtual ICollection<Article> Articles { get; set; }

}

Теперь, когда модель понятна, мы можем определить модель представления, которая будет передана в представление. Модель просмотра - это класс, специально разработанный для представления. Таким образом, в зависимости от того, что вы намерены использовать в этом представлении, вы определяете его в этой модели представления. До сих пор вы говорили только о выпадающем списке, поэтому давайте сделаем это:

public class ArticleViewModel
{
    public int SelectedCategoryId { get; set; }
    public IEnumerable<SelectListItem> Categories { get; set; }
}

а затем у нас есть контроллер:

public class ArticlesController: Controller
{
    private readonly IArticlesRepository _repository;
    public ArticlesController(IArticlesRepository repository)
    {
        _repository = repository;
    }

    public ActionResult Index()
    {
        Article article = _repository.GetArticle();
        ArticleViewModel viewModel = Mapper.Map<Article, ArticleViewModel>(article);
        return View(viewModel);
    }
}

Таким образом, контроллер использует репозиторий для извлечения модели, сопоставляет ее с моделью просмотра (в этом примере я использую AutoMapper) и передает модель представления в представление, которое позаботится об этом:

@model AppName.Models.ArticleViewModel
@using (Html.BeginForm())
{
    @Html.DropDownListFor(
        x => x.SelectedCategoryId, 
        new SelectList(Model.Categories, "Value", "Text"),
        "-- Select category --"
    )
    <input type="submit" value="OK" />
}

Ответ 2

Я тоже это пережил, и я должен согласиться с тем, что сначала это кажется странным (в моем объяснении я предполагаю, что вы хотите выбрать только одну категорию, но процесс очень похож на мульти-выбор).

В основном вам нужно выполнить 3 шага:

1:
Вам нужно два свойства на вашей модели просмотра Один будет содержать выбранный идентификатор категории (требуется для обратной передачи), а другой будет SelectList со всеми возможными категориями:

public class Article
{
    public int ArticleID { get; set; }

    public int CategoryID { get; set; }

    public SelectList Categories { get; set; }
}

2:
Также перед передачей viewmodel на представление вам нужно инициализировать SelectList (Лучше всего подготовить как можно больше, прежде чем передавать модель в представление):

new SelectList(allCategories, "CategoryID", "Name", selectedCategoryID)

3:
В представлении вам нужно добавить свойство ListBox для свойства CategoryID, но с использованием свойства Categories слишком заполнять ListBox значениями:

@Html.ListBoxFor(model => model.CategoryID , Model.Categories)

Вот оно! В ответном действии контроллера у вас будет установлен код категории. Вы можете делать все, что вам нужно, оттуда, чтобы сохранить вещи в своем db.