vista una tutorial pasar net mvc espaƱol datos controlador asp asp.net-mvc asp.net-mvc-3 mvc-editor-templates

asp.net mvc - una - MVC3 EditorTemplate para un booleano anulable usando RadioButtons



pasar datos de una vista a un controlador c# (5)

¿Qué tal un método de extensión divertido para mantener esa "una línea para gobernarlos a todos"? :-)

public static class DictionaryHelper { // This returns the dictionary so that you can "fluently" add values public static IDictionary<TKey, TValue> AddIf<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, bool addIt, TKey key, TValue value) { if (addIt) dictionary.Add(key, value); return dictionary; } }

Y luego, en su archivo de plantilla, simplemente cambia la firma de cómo está agregando los parámetros adicionales, incluido el atributo checked = "checked" al elemento.

@model bool? <div data-ui="buttonset"> @Html.RadioButtonFor(x => x, true, new Dictionary<string,object>() .AddIf(true, "id", ViewData.TemplateInfo.GetFullHtmlFieldId("") + "Yes") .AddIf(Model.HasValue && Model.Value, "checked", "checked") ) <label for="@(ViewData.TemplateInfo.GetFullHtmlFieldId(""))Yes">Yes</label> @Html.RadioButtonFor(x => x, false, new Dictionary<string,object>() .AddIf(true, "id", ViewData.TemplateInfo.GetFullHtmlFieldId("") + "No") .AddIf(Model.HasValue && !Model.Value, "checked", "checked") ) <label for="@(ViewData.TemplateInfo.GetFullHtmlFieldId(""))No">No</label> @Html.RadioButtonFor(x => x, "null", new Dictionary<string,object>() .AddIf(true, "id", ViewData.TemplateInfo.GetFullHtmlFieldId("") + "NA") .AddIf(!Model.HasValue, "checked", "checked") ) <label for="@(ViewData.TemplateInfo.GetFullHtmlFieldId(""))NA">N/A</label> </div>

Tengo una propiedad en uno de mis objetos que es un booleano que puede contener nulos, quiero que mi lógica tenga la representación verdadera Sí, la falsa sea No y la nula sea N / A. Ahora, porque voy a tener varias propiedades como esta en muchos objetos diferentes, tiene más sentido crear un editor y mostrar plantillas para estas propiedades. Voy a usar jQuery UI para aplicar un elemento visual de buttonset después de que todo esto esté funcionando, pero por ahora, eso está fuera del alcance de mi problema. Mi plantilla de editor se ve así.

@model bool? <div data-ui="buttonset"> @Html.RadioButtonFor(x => x, true, new { id = ViewData.TemplateInfo.GetFullHtmlFieldId("") + "Yes"}) <label for="@(ViewData.TemplateInfo.GetFullHtmlFieldId(""))Yes">Yes</label> @Html.RadioButtonFor(x => x, false, new { id = ViewData.TemplateInfo.GetFullHtmlFieldId("") + "No" }) <label for="@(ViewData.TemplateInfo.GetFullHtmlFieldId(""))No">No</label> @Html.RadioButtonFor(x => x, "null", new { id = ViewData.TemplateInfo.GetFullHtmlFieldId("") + "NA" }) <label for="@(ViewData.TemplateInfo.GetFullHtmlFieldId(""))NA">N/A</label> </div>

Mi problema es que bajo ninguna circunstancia puedo obtener esta plantilla de editor para mostrar el valor actual del modelo correctamente. Debido a que no estoy representando una propiedad de un modelo en este ámbito sino el propio modelo, la lógica integrada en MVC3 no establecerá la propiedad marcada correctamente debido a una verificación que se realiza para verificar que el nombre no esté vacío o sea nulo (consulte MVC3 fuente, InputExtensions.cs: línea # 259). No puedo establecer el atributo comprobado dinámicamente en comparación con el Modelo porque el navegador comprueba el botón de radio en presencia del atributo comprobado, no su valor, por lo que aunque mis botones de radio se vean como los siguientes, el último sigue siendo el seleccionado .

<div class="span-4" data-ui="buttonset"> <input checked="checked" id="MyObject_BooleanValueYes" name="MyObject.BooleanValue" type="radio" value="True" /><label for="MyObject_BooleanValueYes">Yes</label> <input checked="" id="MyObject_BooleanValueNo" name="MyObject.BooleanValue" type="radio" value="False" /><label for="MyObject_BooleanValueNo">No</label> <input checked="" id="MyObject_BooleanValueNA" name="MyObject.BooleanValue" type="radio" value="null" /><label for="MyObject_BooleanValueNA">N/A</label> </div><span class="field-validation-valid" data-valmsg-for="MyObject.BooleanValue" data-valmsg-replace="true"></span>&nbsp;</div>

No puedo agregar condicionalmente HtmlAttribute con algo como if?truevalue:falsevalue porque las partes true / false serían de diferentes tipos anónimos y recibo un error.

¿Estoy luchando por cómo se debe hacer esto y espero que alguno de ustedes tenga alguna sugerencia sobre cómo abordar este problema?


El problema es que necesita establecer el atributo checked porque Html.RadioButtonFor no comprueba un botón de Html.RadioButtonFor basado en un bool que pueda Html.RadioButtonFor (lo que parece ser un defecto).

Además, al colocar los botones de radio dentro de la etiqueta de la etiqueta, puede seleccionar el valor haciendo clic en la etiqueta.

Shared / EditorTemplates / Boolean.cshtml

@model bool? <label> <span>n/a</span> @Html.RadioButtonFor(x => x, "", !Model.HasValue ? new { @checked=true } : null) </label> <label> <span>Yes</span> @Html.RadioButtonFor(x => x, true, Model.GetValueOrDefault() ? new { @checked = true } : null) </label> <label> <span>No</span> @Html.RadioButtonFor(x => x, false, Model.HasValue && !Model.Value ? new { @checked = true } : null) </label>


Puedes usar un @helper para simplificar la respuesta aceptada:

@model bool? <div data-ui="buttonset"> @Radio(true, "Yes", "Yes") @Radio(false, "No", "No") @Radio(null, "N/A", "NA") </div> @helper Radio(bool? buttonValue, string buttonLabel, string buttonId) { Dictionary<string, object> attrs = new Dictionary<string, object>(); // Unique button id string id = ViewData.TemplateInfo.GetFullHtmlFieldId("") + buttonId; attrs.Add("id", id); // Check the active button if (Model == buttonValue) { attrs.Add("checked", "checked"); } @Html.RadioButtonFor(m => m, buttonValue, attrs) <label for="@id">@buttonLabel</label> }


Solo necesita manejar el caso nulo especial así:

<label class="radio"> @Html.RadioButtonFor(x => x.DefaultBillable, "", new { @checked = !this.Model.DefaultBillable.HasValue }) Not set </label> <label class="radio"> @Html.RadioButtonFor(x => x.DefaultBillable, "false") Non-Billable </label> <label class="radio"> @Html.RadioButtonFor(x => x.DefaultBillable, "true") Billable </label>


@model bool? <div data-ui="buttonset"> @{ Dictionary<string, object> yesAttrs = new Dictionary<string, object>(); Dictionary<string, object> noAttrs = new Dictionary<string, object>(); Dictionary<string, object> nullAttrs = new Dictionary<string, object>(); yesAttrs.Add("id", ViewData.TemplateInfo.GetFullHtmlFieldId("") + "Yes"); noAttrs.Add("id", ViewData.TemplateInfo.GetFullHtmlFieldId("") + "No"); nullAttrs.Add("id", ViewData.TemplateInfo.GetFullHtmlFieldId("") + "NA"); if (Model.HasValue && Model.Value) { yesAttrs.Add("checked", "checked"); } else if (Model.HasValue && !Model.Value) { noAttrs.Add("checked", "checked"); } else { nullAttrs.Add("checked", "checked"); } } @Html.RadioButtonFor(x => x, "true", yesAttrs) <label for="@(ViewData.TemplateInfo.GetFullHtmlFieldId(""))Yes">Yes</label> @Html.RadioButtonFor(x => x, "false", noAttrs) <label for="@(ViewData.TemplateInfo.GetFullHtmlFieldId(""))No">No</label> @Html.RadioButtonFor(x => x, "null", nullAttrs) <label for="@(ViewData.TemplateInfo.GetFullHtmlFieldId(""))NA">N/A</label> </div>