web-dev-qa-db-ja.com

Asp.NetMVC3-動的ドロップダウンリストを作成する方法

私はこれに関する多くの記事を見つけましたが、それでもこれを正確に行う方法がわかりません。独自のブログエンジンを作成しようとしています。記事を作成するためのビューがあり(最初にEFとコードを使用しています)、記事を追加するカテゴリの番号を入力する必要がありますが、名前をドロップダウンリストに変更したいと思います。カテゴリ。私のモデルはこれに見えます:

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)

NullReferenceExeptionに問題がありますが、理由がわかりません。このようにできますか?それは私にはとても簡単に見えます。

11
Libor Zapletal

あなたのモデルはかなり奇妙に見えます。冗長に見えるCategoryIDCategoryなどのプロパティが含まれています。また、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" />
}
20
Darin Dimitrov

私もこれを経験しましたが、最初は奇妙に思えることに同意する必要があります(私の説明では、1つのカテゴリのみを選択することを想定していますが、プロセスは複数選択の場合と非常に似ています)。

基本的にあなたは実行する必要がありますステップ

1:
ビューモデルに2つのプロパティが必要です。1つは選択したカテゴリID(ポストバックに必要)を保持し、もう1つはすべての可能なカテゴリを含むSelectListを保持します。

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

    public int CategoryID { get; set; }

    public SelectList Categories { get; set; }
}

2:
また、ビューモデルをビューに渡す前に、SelectListを初期化する必要があります(モデルをビューに渡す前に、できるだけ多くの準備をするのが最善の方法です)。

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

3:
ビューで、ListBoxプロパティにCategoryIDを追加する必要がありますが、Categoriesプロパティを使用する場合もListBoxに値を入力します:

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

それでおしまい!コントローラのポストバックアクションでは、CategoryIDが設定されます。データベースに物事を永続化するために、そこから必要なことは何でもできます。

4
ntziolis