Asp.Net MVC3 - 如何创建动态下拉列表

11

我在这方面找到了许多文章,但我仍然不确定该如何做。我正在尝试创建自己的博客引擎,我有一个用于创建文章的视图(我正在使用EF和Code First),现在我必须填写应将文章添加到其中的类别数量,但我想将其更改为下拉列表,其中包含类别名称。我的模型看起来像这样:

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

}

我知道我必须使用枚举(或者我认为是这样),但我不太确定如何使用。我不知道我找到的哪个教程最适合我。


编辑:

感谢你们的答案,但我已经找到了其他东西。我正在尝试这个:

这是我的模型:

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)

我遇到了空引用异常的问题,但我不知道原因。我可以这样做吗?这看起来对我来说很容易。


只使用jQuery UI中默认提供的那个? - Phil C
2个回答

20

你的模型看起来相当奇怪。它包含了一些属性,比如CategoryIDCategory,这些属性似乎是多余的。它还包含一个名为CategoriesSelectListItem集合属性。那么,这是一个模型还是视图模型呢?看起来很混乱。假设它是一个模型,那么它更可能是这样的:

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" />
}

1
我相信CategoryID和Category属性并不是多余的。他只是告诉Entity Framework将外键命名为“CategoryID”,而不是具有下划线的默认值“Category_ID”。 - rajeemcariazo

4
我也经历过这个问题,我必须承认一开始它似乎有些奇怪(在我的解释中,我假设您只想选择一个类别,但对于多选,该过程非常类似)。
基本上,您需要执行3个步骤
1:
您的视图模型需要两个属性: 一个将保存所选类别的ID(在提交后需要),另一个是包含所有可能类别的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)

就是这样!在控制器的后端操作中,您将设置CategoryID。从那里,您可以做任何必要的事情来持久化您的数据库。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接