Associazione di DropDownList dal database

Nov 24 2020

Sto costruendo una vista che mostrerà i dati tabulari in base alle selezioni da due elenchi a discesa, il primo che seleziona i reparti viene popolato dal database. Il secondo è un elenco a discesa statico per "Anno" che non ho ancora avuto modo di conoscere. Ci sono risposte a domande simili, ma le ho esaminate e ho provato di tutto. Sono arrivato al punto in cui ottengo un'eccezione nulla nella vista in cui ho creato il markup per l'elenco a discesa.

Visualizza:

I dipartimenti tornano come nulli. Sono nuovo in MVC e l'ho messo insieme da esempi online . Immagino che il mio modello sia sbagliato.

@model IEnumerable<BudgetDemo.Models.BudgetsActualsViewModel>

@foreach (var item in Model)
{
    @Html.DropDownListFor(m => item.Departments, 
        new SelectList(item.Departments.Select(x => x.Text)))
}

ViewModel:

public class BudgetsActualsViewModel
{
    [Display(Name = "Cost Center/Department")]
    [Required(ErrorMessage = "Cost Center/Department is required.")]
    [StringLength(62)]
    public string SelectedDepartment { get; set; }
    public IEnumerable<SelectListItem> Departments { get; set; }
}

Controller:

public ActionResult GetBudgetsActuals()   
{
    repo = new BudgetDemoRepository();
    ModelState.Clear();
    return View(repo.GetBudgetsActuals());
}

Classe repository:

public List<BudgetsActualsViewModel> GetBudgetsActuals()  
{
    ...
    List<BudgetsActualsViewModel> budgetsActualsList = new List<BudgetsActualsViewModel>();
    // Query returning correct data from DB here

    for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
    {
        budgetsActualsList.Add(
            new BudgetsActualsViewModel
             {
                 SelectedDepartment = ds.Tables[0].Rows[i]["Department"].ToString()
             }
        );
    }
    return budgetsActualsList;
}

Risposte

1 JamshaidK. Nov 24 2020 at 06:13

Quindi, stai salvando i valori in SelectedDepartmentproprietà e accedendo Departmentsall'elenco. Che non è mai inizializzato quindi sarebbe ovviamente null.

Modifica il tuo GetBudgetsActualsmetodo in questo modo:

public BudgetsActualsViewModel GetBudgetsActuals()  
{
    ...
    BudgetsActualsViewModel budgetsActuals = new BudgetsActualsViewModel(){ Departments = new List<SelectListItem>() };
    // Query returning correct data from DB here

    for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
    {
        budgetsActuals.Departments
                      .Add(new SelectListItem 
                          { 
                              Text = ds.Tables[0].Rows[i]["Department"].ToString(), 
                              Value = ds.Tables[0].Rows[i]["YourRowId"].ToString() 
                          });
    }
    return budgetsActuals;
}

Ed ecco come dovrebbe apparire la tua vista:

@model BudgetDemo.Models.BudgetsActualsViewModel
@Html.DropDownListFor(m => m.SelectedDepartment, Model.Departments))

Nota, ci siamo sbarazzati del foreachloop. Abbiamo bisogno che il DropDownListFor()metodo venga chiamato solo una volta.


AGGIORNARE

public class BudgetsActualsViewModel
{
    [Display(Name = "Cost Center/Department")]
    [Required(ErrorMessage = "Cost Center/Department is required.")]
    [StringLength(62)]
    public string SelectedDepartment { get; set; }
    public List<SelectListItem> Departments { get; set; } // Modify it to list instead IEnumerable.
}