web-dev-qa-db-fra.com

Remplir DropDownList dans ASP.NET MVC à partir d'une table de base de données à l'aide de Entity Framework 6 et ViewModel

Je me gratte la tête depuis une nuit entière sur un problème que je peux résoudre rapidement en utilisant ajax/jquery et les procédures stockées. je veux 

1) Remplissez une liste déroulante à partir de valeurs obtenues à partir d'une table de base de données à l'aide d'Entity Framework et du modèle d'affichage. JE NE VEUX PAS UTILISER VIEWBAG OR VIEWDATA. Toute aide appréciée.

2) Comment puis-je générer une vue Créer à l'aide du modèle de vue avec tous les champs par défaut? L'échafaudage fonctionne sur un modèle mais pas sur un modèle de vue?

MES MODÈLES

public class Employee
{
    public int EmployeeID { get; set; }
    public string Name { get; set; }
    public string Gender { get; set; }
    public string City { get; set; }
    public string Level { get; set; }
    public int DepartmentId { get; set; }
}

public class Grade
{
    public int ID { get; set; }
    public string Level { get; set; }
}

Voir le modèle

public class GradeSelectListViewModel
{

    public Employee Employee { get; set; }
    public IEnumerable<SelectListItem> Grades { get; set; }
    public GradeSelectListViewModel(Employee employee, IEnumerable grades)
    {
        Employee = employee;
        Grades = new SelectList(grades, "Grade", "Name", employee.Level);
    }
}

MA CLASSE DE CONTEXTE

public class EmployeeContext : DbContext
{
    public DbSet<Employee> Employees { get; set; }
    public DbSet<Department> Departments { get; set; }
    public DbSet<Grade> Grades { get; set; }
}

MON CONTRÔLEUR

public ActionResult Edit (int? id)
{
    using (var db = new EmployeeContext())
    {
        var model = new GradeSelectListViewModel(db.Employees.Find(id), db.Grades);
        //model.Employee = db.Employees.Single(x => x.EmployeeID == id);
        model.Grades = db.Grades.ToList().Select(x => new SelectListItem
        {
            Value = x.ID.ToString(),
            Text = x.Level
        });
        return View(model);
    }
}

MON PAGE DE RASOIR CSHTML

@model MVCDemo.ViewModels.GradeSelectListViewModel
....
@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()
    ....
    @Html.DropDownListFor(x => Model.Employee.Level,
        new SelectList(Model.Grades, "ID", "Level"),
        "Select Level")
    ....
    <input type="submit" value="Create" class="btn btn-default" />
}
4
TropicalViking

Le problème principal est que, dans la vue, vous avez new SelectList(Model.Grades, "ID", "Level") mais Grades est IEnumerable<SelectListItem> et SelectListItem ne contient pas de propriétés nommées ID et Level.

Cependant, il y a quelques autres problèmes avec votre code. Tout d'abord, un modèle de vue ne doit pas contenir de modèle de données, mais votre modèle de vue doit être

public class GradeSelectListViewModel
{
    public int? ID { get; set; } // make this ID so you do not need an input for it
    public string Name { get; set; }
    .... // other properties of Employee that your editing
    [Required(ErrorMessage = "..")]
    public int? Level { get; set; } // make value types nullable to protect against under-posting attacks
    public IEnumerable<SelectListItem> Grades { get; set; }
}

et ajoutez les attributs d'affichage et de validation nécessaires. Notez que j'ai supprimé le constructeur (vous ne semblez pas l'utiliser, mais si c'est le cas, vous devez également inclure un constructeur sans paramètre, sinon une exception sera levée lors de la soumission à la méthode POST. Je suppose également que Level devrait être typeof int puisque vous liez à la propriété int ID de Grade.

Le code dans votre méthode GET devrait être

Employee employee = db.Employees.Find(id);
var model = new GradeSelectListViewModel()
{
    ID = employee.EmployeeID,
    Name = employee.Name,
    Level = employee.Level, // convert to int?
    ....
    Grades = db.Grades.Select(x => new SelectListItem
    {
        Value = x.ID.ToString(),
        Text = x.Level
    })
};
return View(model);

et dans la vue

 @Html.DropDownListFor(x => Model.Level, Model.Grades, "Select Level")

Notez également que dans la méthode POST, vous devez réaffecter la SelectList si vous renvoyez la vue car ModelState est invalide.

7
user3559349

Vous pouvez utiliser l'approche suivante pour renseigner trois DropDownListFor dans la même vue:

ViewModel:

public class GroupViewModel
{  
    public IEnumerable<SelectListItem> Schedules { get; set; }
    public int ScheduleId { get; set; }

    public IEnumerable<SelectListItem> Labs { get; set; }
    public int LabId { get; set; }

    public IEnumerable<SelectListItem> Terms { get; set; } 
    public int TermId { get; set; }
}



Manette:

public ActionResult Create()
{
    //Populate DropDownList binding values
    var model = new GroupViewModel
    {
        //Preselect the Lab with id 2
        //LabId = 2,

        Labs = repository.Labs.Select(c => new SelectListItem
        {
            Value = c.Id.ToString(),
            Text = c.Name
        }),
        Terms = repository.Terms.Select(c => new SelectListItem
        {
            Value = c.Id.ToString(),
            Text = c.Name
        }),
        Schedules = repository.Schedules.Select(c => new SelectListItem
        {
            Value = c.Id.ToString(),
            Text = c.Name
        })
    };
    return View("Create", model);
}



Vue:

@Html.DropDownListFor(m => m.LabId, new SelectList(Model.Labs, "Value", "Text"), 
    "Select", new { @class = "selectpicker" })

@Html.DropDownListFor(m => m.ScheduleId, new SelectList(Model.Schedules, "Value", "Text"), 
    "Select", new { @class = "selectpicker" })

@Html.DropDownListFor(m => m.TermId, new SelectList(Model.Terms, "Value", "Text"), 
    "Select", new { @class = "selectpicker" })

J'espère que cela t'aides...

1
Murat Yıldız