2011-08-25 5 views
11

Sto usando ASP.NET MVC3 con Razor e C#. Sto facendo un costruttore forma di sorta, quindi ho un modello che ha una collezione di seguente oggetto:Come posso far funzionare Html.CheckBoxFor() su un campo stringa?

public class MyFormField 
{ 
    public string Name { get; set; } 
    public string Value { get; set; } 
    public MyFormType Type { get; set; } 
} 

MyFormType è solo un enum che mi dice se il campo di modulo è una casella di controllo, o di testo, o caricamento di file o altro. Il mio editor di modelli simile a questa (si veda il commento):

~/Vista/EditorTemplates/MyFormField.cshtml

@model MyFormField 
@{ 
    switch (Model.Type) 
    { 
     case MyFormType.Textbox: 
      @Html.TextBoxFor(m => m.Value) 
     case MyFormType.Checkbox: 
      @Html.CheckBoxFor(m => m.Value) // This does not work! 
    } 
} 

ho provato fusione/convertire il m.Value ad un bool nell'espressione lambda per CheckBoxFor(), ma che ha generato un errore. Vorrei solo costruire manualmente un ingresso casella di controllo, ma CheckBoxFor() sembra fare due cose che io non riesco a replicare:

  1. crea un input nascosto che in qualche modo viene popolato dalla casella di controllo. Questo sembra essere ciò che raccoglie il raccoglitore modello.
  2. Genera il nome modulo dell'oggetto in modo che il raccoglitore modello ottenga il valore nella proprietà corretta.

Qualcuno sa un modo per aggirare utilizzando CheckBoxFor() su una stringa, o un modo per replicare la funzionalità manualmente, in modo che io possa fare questo lavoro?

risposta

11

Si potrebbe anche aggiungere una proprietà sulla vostra viewmodel:

public class MyFormField 
    { 
     public string Name { get; set; } 
     public string Value { get; set; } 

     public bool CheckBoxValue 
     { 
      get { return Boolean.Parse(Value); } 
     } 

     public MyFormType Type { get; set; } 
    } 

tuo punto di vista sarebbe essere qualcosa del genere:

@model MyFormField 
@{ 
    switch (Model.Type) 
    { 
     case MyFormType.Textbox: 
      @Html.TextBoxFor(m => m.Value) 
     case MyFormType.Checkbox: 
      @Html.CheckBoxFor(m => m.CheckBoxValue) // This does work! 
    } 
} 

Usa Boolean.TryParse se vuoi evitare le eccezioni.

+0

Grazie!Questo ha risolto il mio problema che stavo avendo! – AustinT

10

Un modo è creare il proprio metodo di estensione htmlhelper.

public static MvcHtmlString CheckBoxStringFor<TModel>(this HtmlHelper<TModel> html, Expression<Func<TModel, string>> expression) 
    { 
     // get the name of the property 
     string[] propertyNameParts = expression.Body.ToString().Split('.'); 
     string propertyName = propertyNameParts.Last(); 

     // get the value of the property 
     Func<TModel, string> compiled = expression.Compile(); 
     string booleanStr = compiled(html.ViewData.Model); 

     // convert it to a boolean 
     bool isChecked = false; 
     Boolean.TryParse(booleanStr, out isChecked); 

     TagBuilder checkbox = new TagBuilder("input"); 
     checkbox.MergeAttribute("id", propertyName); 
     checkbox.MergeAttribute("name", propertyName); 
     checkbox.MergeAttribute("type", "checkbox"); 
     checkbox.MergeAttribute("value", "true"); 
     if (isChecked) 
      checkbox.MergeAttribute("checked", "checked"); 

     TagBuilder hidden = new TagBuilder("input"); 
     hidden.MergeAttribute("name", propertyName); 
     hidden.MergeAttribute("type", "hidden"); 
     hidden.MergeAttribute("value", "false"); 

     return MvcHtmlString.Create(checkbox.ToString(TagRenderMode.SelfClosing) + hidden.ToString(TagRenderMode.SelfClosing)); 
    } 

l'utilizzo è lo stesso di CheckBoxFor helper (e.Value è una stringa)

@Html.CheckBoxStringFor(e => e.Value) 
+0

Penso avvolgendo la proprietà è il modo il modo più semplice/pulito in questa situazione, ma io votare per questa spiegazione. Ho cercato il codice dalle prime due sezioni del tuo metodo, quindi grazie per quella parte! – jrizzo

0

Ho avuto questo problema, ma non è stato in grado di modificare il modello di visualizzazione. Ho provato la soluzione mdm20s ma come sospettavo non funzionasse sulle proprietà della raccolta (non aggiunge gli indici ai nomi e agli id ​​come gli helper HTML nativi). Per superare questo è possibile utilizzare invece Html.CheckBox. Aggiunge gli indici corretti e puoi passare tu stesso il valore della casella.

Se si desidera utilizzare un'espressione, è sempre possibile scrivere un wrapper simile a mdm20s ma sostituire tutto dopo TryParse con return Html.CheckBox("propertyName", isChecked). Ovviamente sarà necessario aggiungere anche using System.Web.Mvc.Html.

3

Utilizzare la casella di controllo, in questo modo semplice funziona bene

@Html.CheckBox("IsActive", Model.MyString == "Y" ? true : false) 
+3

Non hai bisogno del '? vero: parte falsa. 'Model.MyString ==" Y "' è già un booleano. – Alexander