web-dev-qa-db-fra.com

MVC DropDownList SelectedValue ne s'affiche pas correctement

J'ai essayé de chercher et je n'ai rien trouvé qui résolve mon problème. J'ai un DropDownList sur une vue Razor qui ne montrera pas l'élément que j'ai marqué comme sélectionné dans la liste de sélection. Voici le code du contrôleur qui remplit la liste:

var statuses  = new SelectList(db.OrderStatuses, "ID", "Name", order.Status.ID.ToString());
ViewBag.Statuses = statuses;
return View(vm);

Voici le code de vue:

<div class="display-label">
   Order Status</div>
<div class="editor-field">
   @Html.DropDownListFor(model => model.StatusID, (SelectList)ViewBag.Statuses)
   @Html.ValidationMessageFor(model => model.StatusID)
</div>

Je le parcoure et, même dans la vue, il a la valeur SelectedValue correcte, mais le DDL affiche toujours le premier élément de la liste, quelle que soit la valeur sélectionnée. Est-ce que n'importe qui peut indiquer ce que je fais mal pour obtenir le DDL pour mettre par défaut à SelectValue?

19
azorr

Le dernier argument du constructeur SelectList (dans lequel vous espérez pouvoir transmettre l'id de la valeur sélectionnée) est ignoré car l'assistant DropDownListFor utilise l'expression lambda que vous avez transmise comme premier argument et utilise la valeur de la propriété spécifique.

Alors voici la mauvaise façon de faire ça:

Modèle:

public class MyModel
{
    public int StatusID { get; set; }
}

Manette:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        // TODO: obviously this comes from your DB,
        // but I hate showing code on SO that people are
        // not able to compile and play with because it has 
        // gazzilion of external dependencies
        var statuses = new SelectList(
            new[] 
            {
                new { ID = 1, Name = "status 1" },
                new { ID = 2, Name = "status 2" },
                new { ID = 3, Name = "status 3" },
                new { ID = 4, Name = "status 4" },
            }, 
            "ID", 
            "Name"
        );
        ViewBag.Statuses = statuses;

        var model = new MyModel();
        model.StatusID = 3; // preselect the element with ID=3 in the list
        return View(model);
    }
}

Vue:

@model MyModel
...    
@Html.DropDownListFor(model => model.StatusID, (SelectList)ViewBag.Statuses)

et voici la bonne façon, en utilisant le modèle de vue réelle:

Modèle

public class MyModel
{
    public int StatusID { get; set; }
    public IEnumerable<SelectListItem> Statuses { get; set; }
}

Manette:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        // TODO: obviously this comes from your DB,
        // but I hate showing code on SO that people are
        // not able to compile and play with because it has 
        // gazzilion of external dependencies
        var statuses = new SelectList(
            new[] 
            {
                new { ID = 1, Name = "status 1" },
                new { ID = 2, Name = "status 2" },
                new { ID = 3, Name = "status 3" },
                new { ID = 4, Name = "status 4" },
            }, 
            "ID", 
            "Name"
        );
        var model = new MyModel();
        model.Statuses = statuses;
        model.StatusID = 3; // preselect the element with ID=3 in the list
        return View(model);
    }
}

Vue:

@model MyModel
...    
@Html.DropDownListFor(model => model.StatusID, Model.Statuses)
46
Darin Dimitrov

Créez un modèle de vue pour chaque vue. En procédant ainsi, vous n'incluerez que ce qui est nécessaire à l'écran. Comme je ne sais pas où vous utilisez ce code, supposons que vous ayez une vue Créer pour ajouter une nouvelle commande.

Créez un nouveau modèle de vue pour votre vue Créer:

public class OrderCreateViewModel
{
     // Include other properties if needed, these are just for demo purposes

     // This is the unique identifier of your order status,
     // i.e. foreign key in your order table
     public int OrderStatusId { get; set; }
     // This is a list of all your order statuses populated from your order status table
     public IEnumerable<OrderStatus> OrderStatuses { get; set; }
}

Classe d'état de la commande:

public class OrderStatus
{
     public int Id { get; set; }
     public string Name { get; set; }
}

Dans votre vue Créer, vous obtenez les éléments suivants:

@model MyProject.ViewModels.OrderCreateViewModel

@using (Html.BeginForm())
{
     <table>
          <tr>
               <td><b>Order Status:</b></td>
               <td>
                    @Html.DropDownListFor(x => x.OrderStatusId,
                         new SelectList(Model.OrderStatuses, "Id", "Name", Model.OrderStatusId),
                         "-- Select --"
                    )
                    @Html.ValidationMessageFor(x => x.OrderStatusId)
               </td>
          </tr>
     </table>

     <!-- Add other HTML controls if required and your submit button -->
}

Vos méthodes d'action Create:

public ActionResult Create()
{
     OrderCreateViewModel viewModel = new OrderCreateViewModel
     {
          // Here you do database call to populate your dropdown
          OrderStatuses = orderStatusService.GetAllOrderStatuses()
     };

     return View(viewModel);
}

[HttpPost]
public ActionResult Create(OrderCreateViewModel viewModel)
{
     // Check that viewModel is not null

     if (!ModelState.IsValid)
     {
          viewModel.OrderStatuses = orderStatusService.GetAllOrderStatuses();

          return View(viewModel);
     }

     // Mapping

     // Insert order into database

     // Return the view where you need to be
}

Cela persistera vos sélections lorsque vous cliquerez sur le bouton d'envoi et que vous serez redirigé vers la vue Créer pour la gestion des erreurs.

J'espère que ça aide.

2
Brendan Vogt

Assurez-vous que votre valeur de sélection renvoyée est une chaîne et non pas int lorsque vous la déclarez dans votre modèle.

Exemple:

public class MyModel
{
    public string StatusID { get; set; }
}
1
p.sturge

Pour moi, le problème était causé par les nombres de remplissage en gros css (remplissage en haut et en bas dans le champ déroulant). Fondamentalement, l'élément était montré mais n'était pas visible car il était très bas. Je l'ai FIXE en réduisant mes nombres de remplissage.

0
JPTugirimana

Je laisse cela au cas où cela aiderait quelqu'un d'autre. J'ai eu un problème très similaire et aucune des réponses n'a aidé.

Mon ViewData contenait une propriété portant le même nom que le sélecteur de l'expression lambda, comme si vous aviez eu ViewData["StatusId"] défini sur quelque chose.

Après avoir modifié le nom de la propriété anonyme dans ViewData, l’assistant DropDownList a fonctionné comme prévu.

Bizarre cependant.

0
Alberto Sadoc