2012-04-12 5 views
6

Mein Modell ist wie folgt:auf Post, eine Dropdown-Liste SelectList.SelectedValue ist null

public class testCreateModel 
{ 
    public string s1 { get; set; } 
    public SelectList DL { get; set; } 

    public testCreateModel() 
    { 
     Dictionary<string, string> items = new Dictionary<string, string>(); 
     items.Add("1", "Item 1"); 
     items.Add("2", "Item 2"); 
     DL = new SelectList(items, "Key", "Value"); 
    } 
} 

Meine Einleitung von Maßnahmen ist:

public ActionResult testCreate() 
    { 
     testCreateModel model = new testCreateModel(); 
     return View(model); 
    } 

Mein Razor Ansicht (irrelevante Teile gestrichen) ist:

@model Tasks.Models.testCreateModel 

@using (Html.BeginForm()) { 
<fieldset> 
    <legend>testCreateModel</legend> 

    <div class="editor-label"> 
     @Html.LabelFor(model => model.s1) 
    </div> 
    <div class="editor-field"> 
     @Html.EditorFor(model => model.s1) 
    </div> 

    <div class="editor-label"> 
     Select an item: 
    </div> 
    <div class="editor-field"> 
     @Html.DropDownList("dropdownlist", (SelectList)Model.DL) 
    </div> 

    <p> 
     <input type="submit" value="Create" /> 
    </p> 
</fieldset> 
} 

Die Post zurück Aktion:

Auf Post zurück, ist model.DL.SelectedValue null. (Das ausgewählte Element kann jedoch aus FormCollection abgerufen werden, aber das ist neben dem Punkt). Das DL-Objekt noch richtig sonst bevölkert, Direkt-Fenster wie folgt ausgegeben:

model.DL 
{System.Web.Mvc.SelectList} 
    base {System.Web.Mvc.MultiSelectList}: {System.Web.Mvc.SelectList} 
    SelectedValue: null 
model.DL.Items 
Count = 2 
    [0]: {[1, Item 1]} 
    [1]: {[2, Item 2]} 
model.DL.SelectedValue 
null 

Q1: Wie kann ich die Verwendung der SelectedValue Eigenschaft machen statt?

Wenn nun in der Razor Ansicht, die ich den Namen des HTML-SELECT-Tages DL (dh gleich den Eigenschaftsnamen im Modell) ändern:

@Html.DropDownList("DL", (SelectList)Model.DL) 

Ich erhalte eine Ausnahme:

No parameterless constructor defined for this object. 
Stack Trace: 
[MissingMethodException: No parameterless constructor defined for this object.] 
System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0 
System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache) +98 
System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean skipCheckThis, Boolean fillCache) +241 
System.Activator.CreateInstance(Type type, Boolean nonPublic) +69 
System.Web.Mvc.DefaultModelBinder.CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) +199 
System.Web.Mvc.DefaultModelBinder.BindSimpleModel(ControllerContext controllerContext, ModelBindingContext bindingContext, ValueProviderResult 
... 

Q2: Warum?

Danke.

Antwort

11

MVC kehrt nur den Wert der ausgewählten Option in Ihrem POST, so dass Sie eine Eigenschaft müssen die einzelnen Wert enthalten, die zurückgibt.

Als guter Rat, versuchen SelectLists durch ViewBag Einstellung, das hilft von Daten sauber Ihre Viewmodel zu halten, die die Form füllen muss.

So könnte Ihr Beispiel wie folgt gelöst werden:

public class testCreateModel 
{ 
    public string s1 { get; set; } 
    public int SelectedValue { get; set; } 
} 

und in Ihrer Ansicht gerade dies zu tun:

@Html.DropDownList("SelectedValue", (SelectList)ViewBag.DL) 

vor ViewBag.DL in Ihrer GET Aktion zu bevölkern.

Was Ihre Q2 erfordert die Standard-Modelbinder, dass alle Typen einen Standardkonstruktor haben zu binden (so dass der Modelbinder können sie erstellen)

+0

Vielen Dank für die vorgeschlagene Methode zur Verwendung einer Dropdown-Liste. Es funktioniert und es wird weniger Arbeit benötigt, um den ausgewählten Wert zu übernehmen! –

+0

Danke, dies ist der beste Beitrag, der mich in Bezug auf die Verwendung von Dropdownliste in mvc –

10

Eine Antwort ausgewählt wurde, sondern schauen, wie ich es tat. Unten ist Code, wie ich es normalerweise mache, wenn ich ein Drop-Down-Menü bevölkere. Es ist sehr einfach, ich schlage vor, Sie verwenden es als Basis, um Ihre Dropdowns zu erstellen.

An der Spitze meiner Sicht ich meine Ansicht Modell angeben:

@model MyProject.ViewModels.MyViewModel 

Auf meiner Sicht habe ich eine Dropdown-Liste, die die Banken alles, was aus kann ein Benutzer anzeigt wählen:

<table> 
    <tr> 
      <td><b>Bank:</b></td> 
      <td> 
       @Html.DropDownListFor(
        x => x.BankId, 
        new SelectList(Model.Banks, "Id", "Name", Model.BankId), 
        "-- Select --" 
       ) 
       @Html.ValidationMessageFor(x => x.BankId) 
      </td> 
    </tr> 
</table> 

Ich habe immer ein Ansichtsmodell für eine Ansicht, ich übergebe kein Domänenobjekt direkt an die Ansicht. In diesem Fall wird meiner Ansicht nach Modell eine Liste der Banken enthalten, die aus der Datenbank gefüllt werden:

public class MyViewModel 
{ 
    // Other properties 

    public int BankId { get; set; } 
    public IEnumerable<Bank> Banks { get; set; } 
} 

Meine Bank Domain-Modell:

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

Dann in meine Aktionsmethode erstelle ich eine Instanz meiner Modell anzeigen und die Bankliste aus der Datenbank auffüllen. Sobald dies erledigt ist, gebe ich das Ansichtsmodell zur Ansicht zurück:

public ActionResult MyActionMethod() 
{ 
    MyViewModel viewModel = new ViewModel 
    { 
      // Database call to get all the banks 
      // GetAll returns a list of Bank objects 
      Banks = bankService.GetAll() 
    }; 

    return View(viewModel); 
} 

[HttpPost] 
public ActionResult MyActionMethod(MyViewModel viewModel) 
{ 
    // If you have selected an item then BankId would have a value in it 
} 

Ich hoffe, das hilft.

+0

hepled Excellent und vielen Dank für die Freigabe. Ich habe jedoch Probleme beim Abrufen der Daten im Postback des Formulars. Irgendwelche Ideen? Vielen Dank –