ASP.NET MVC tak / nie przyciski radiowe z silnie powiązanym modelem MVC

132

Czy ktoś wie, jak powiązać przycisk opcji tak / nie z właściwością logiczną modelu z silną typizacją w ASP.NET MVC.

Model

public class MyClass
{
     public bool Blah { get; set; }
}

Widok

<%@  Page Title="blah"  Inherits="MyClass"%>
    <dd>
        <%= Html.RadioButton("blah", Model.blah) %> Yes
        <%= Html.RadioButton("blah", Model.blah) %> No
    </dd>

Dzięki

ROZWIĄZANIE:

Dziękuję Brianowi za wskazówki, ale było to przeciwieństwo tego, co napisał. Jak tak -

<%@  Page Title="blah"  Inherits="MyClass"%>
<dd>
    <%= Html.RadioButton("blah", !Model.blah) %> Yes
    <%= Html.RadioButton("blah", Model.blah) %> No
</dd>
brianstewey
źródło
4
„Problem” z tymi rozwiązaniami (a ja używam stylu Bena Culla w moim projekcie) polega na tym, że nie można z nimi tworzyć etykiet. Oba wejścia przycisków opcji będą miały ten sam identyfikator i nazwę, więc jeśli użyjesz Html.LabelFor, będzie on łączył się z pierwszym wejściem przycisku opcji w DOM o tym identyfikatorze. Tak jak powiedziałem, używam tego rozwiązania dla przycisków radiowych, aby reprezentować pole boolowskie, chciałem tylko, aby ludzie wiedzieli, że etykiety będą trochę chwiejne.
Gromer
2
Zobacz odpowiedź Jeffa Bobisha, aby dowiedzieć się, jak elegancko rozwiązać problem z etykietą.
René

Odpowiedzi:

74

Drugi parametr jest wybrany, więc użyj! aby wybrać wartość no, gdy wartość logiczna ma wartość false.

<%= Html.RadioButton("blah", !Model.blah) %> Yes 
<%= Html.RadioButton("blah", Model.blah) %> No 
Brian Mains
źródło
198

Jeśli używasz MVC 3 i Razor, możesz również użyć następujących elementów:

@Html.RadioButtonFor(model => model.blah, true) Yes
@Html.RadioButtonFor(model => model.blah, false) No
Ben Cull
źródło
56

Oto bardziej kompletny przykład, w którym zastosowano a fieldsetze względu na dostępność i określono pierwszy przycisk jako domyślny. Bez a fieldset, do czego służą przyciski radiowe jako całość, nie można określić programowo.

Model

public class MyModel
{
    public bool IsMarried { get; set; }
}

Widok

<fieldset>
    <legend>Married</legend>

    @Html.RadioButtonFor(e => e.IsMarried, true, new { id = "married-true" })
    @Html.Label("married-true", "Yes")

    @Html.RadioButtonFor(e => e.IsMarried, false, new { id = "married-false" })
    @Html.Label("married-false", "No")
</fieldset>

Możesz dodać @checkedargument do obiektu anonimowego, aby ustawić przycisk opcji jako domyślny:

new { id = "married-true", @checked = 'checked' }

Zwróć uwagę, że możesz powiązać się z łańcuchem, zastępując truei falseużywając wartości ciągu.

Daniel Imms
źródło
W rzeczywistości powinieneś użyć nowego {id = Html.Id ("married-true")}, zmniejszając potencjalne problemy z zakresem generowanych przedrostków identyfikatorów.
eoleary
26

Opierając się nieco na odpowiedzi Bena, dodałem atrybuty do identyfikatora, aby móc używać etykiet.

<%: Html.Label("isBlahYes", "Yes")%><%= Html.RadioButtonFor(model => model.blah, true, new { @id = "isBlahYes" })%>
<%: Html.Label("isBlahNo", "No")%><%= Html.RadioButtonFor(model => model.blah, false, new { @id = "isBlahNo" })%>

Mam nadzieję, że to pomoże.

ctc
źródło
7
Zwykle etykieta znajduje się po przycisku opcji.
Daniel Imms,
6
Umieszczenie etykiety wokół przycisku opcji jest całkowicie poprawne.
Scott Baker
23

Dodanie tagów etykiet wokół przycisków opcji przy użyciu zwykłego kodu HTML rozwiązuje również problem z „labelfor”:

<label><%= Html.RadioButton("blah", !Model.blah) %> Yes</label>
<label><%= Html.RadioButton("blah", Model.blah) %> No</label>

Kliknięcie tekstu powoduje teraz wybranie odpowiedniego przycisku opcji.

Jeff Bobish
źródło
8

lub MVC 2.0:

<%= Html.RadioButtonFor(model => model.blah, true) %> Yes
<%= Html.RadioButtonFor(model => model.blah, false) %> No
Stafford Williams
źródło
5

Jeśli uda mi się wrzucić kapelusz do ringu, myślę, że istnieje prostszy sposób na ponowne wykorzystanie funkcji przycisku radiowego niż dotychczasowe odpowiedzi.

Załóżmy, że masz następującą właściwość w swoim ViewModel :

Public Class ViewModel
    <Display(Name:="Do you like Cats?")>
    Public Property LikesCats As Boolean
End Class

Możesz udostępnić tę właściwość za pomocą szablonu edytora wielokrotnego użytku :

Najpierw utwórz plik Views/Shared/EditorTemplates/YesNoRadio.vbhtml

Następnie dodaj następujący kod do YesNoRadio.vbhtml :

@ModelType Boolean?

<fieldset>
    <legend>
        @Html.LabelFor(Function(model) model)
    </legend>

    <label>
        @Html.RadioButtonFor(Function(model) model, True) Yes
    </label>
    <label>
        @Html.RadioButtonFor(Function(model) model, False) No
    </label>
</fieldset>

Możesz wywołać edytor właściwości, ręcznie określając nazwę szablonu w widoku :

@Html.EditorFor(Function(model) model.LikesCats, "YesNoRadio")

Plusy:

  • Zacznij pisać HTML w edytorze HTML zamiast dołączać ciągi w kodzie za nim.
  • Zachowuje DisplayName DataAnnotation
  • Umożliwia kliknięcie etykiety, aby przełączyć przycisk opcji
  • Najmniejszy kod do utrzymania w postaci (1 linia). Jeśli coś jest nie tak ze sposobem, w jaki się rozdziera, zajmij się tym szablonem.
KyleMit
źródło
To dobrze, ale co z trzecią opcją dla wartości logicznych? @ Html.RadioButtonFor (Function (Model) Model.IsVerified, True) <span> Tak </span> @ Html.RadioButtonFor (Function (Model) Model.IsVerified, False) <span> Nie </span> @ Html.RadioButtonFor (Funkcja (model) Model.IsVerified, Nothing)) <span> Oczekiwanie </span>
JoshYates1980
1

Skończyło się na tym, że zapakowałem to w metodę rozszerzenia, więc (1) mogłem wygenerować etykietę i radio naraz oraz (2), więc nie musiałem zawracać sobie głowy określaniem własnych identyfikatorów:

public static class HtmlHelperExtensions
{
    public static MvcHtmlString RadioButtonAndLabelFor<TModel, TProperty>(this HtmlHelper<TModel> self, Expression<Func<TModel, TProperty>> expression, bool value, string labelText)
    {
        // Retrieve the qualified model identifier
        string name = ExpressionHelper.GetExpressionText(expression);
        string fullName = self.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);

        // Generate the base ID
        TagBuilder tagBuilder = new TagBuilder("input");
        tagBuilder.GenerateId(fullName);
        string idAttr = tagBuilder.Attributes["id"];

        // Create an ID specific to the boolean direction
        idAttr = String.Format("{0}_{1}", idAttr, value);

        // Create the individual HTML elements, using the generated ID
        MvcHtmlString radioButton = self.RadioButtonFor(expression, value, new { id = idAttr });
        MvcHtmlString label = self.Label(idAttr, labelText);

        return new MvcHtmlString(radioButton.ToHtmlString() + label.ToHtmlString());
    }
}

Stosowanie:

@Html.RadioButtonAndLabelFor(m => m.IsMarried, true, "Yes, I am married")
atak
źródło