it-swarm.com.de

Ankreuzfeld für nullwertfähige boolesche Werte

Mein Modell hat einen Booleschen Wert, der nullwertfähig sein muss

public bool? Foo
{
   get;
   set;
}

so in meinem Razor cshtml habe ich

@Html.CheckBoxFor(m => m.Foo)

außer das funktioniert nicht. Es wirkt auch nicht mit (bool). Wenn ich mache

@Html.CheckBoxFor(m => m.Foo.Value)

das erzeugt zwar keinen Fehler, bindet sich jedoch nicht an mein Modell, wenn es veröffentlicht wird und foo auf null gesetzt ist. Was ist der beste Weg, um Foo auf der Seite anzuzeigen und es in einem Beitrag an mein Modell zu binden?

84
DMulligan

Ich habe es mit zu arbeiten 

@Html.EditorFor(model => model.Foo) 

und dann eine Boolean.cshtml in meinem EditorTemplates-Ordner erstellen und kleben 

@model bool?

@Html.CheckBox("", Model.GetValueOrDefault())

innerhalb.

98
DMulligan

Antwort in ähnlicher Frage gefunden - Rendern von Nullable Bool als CheckBox . Es ist sehr unkompliziert und funktioniert einfach:

@Html.CheckBox("RFP.DatesFlexible", Model.RFP.DatesFlexible ?? false)
@Html.Label("RFP.DatesFlexible", "My Dates are Flexible")

Es ist wie eine akzeptierte Antwort von @afinkelstein, außer dass wir keine spezielle 'Editorvorlage' brauchen.

35
resnyanskiy

Ich habe bool? IsDisabled { get; set; } in Model. Eingefügt, wenn in Ansicht.

<div class="inputClass" id="disabled">
    <div>
    @if(Model.IsDisabled==null)
    {
        Model.IsDisabled = false;
    }           
    @Html.CheckBoxFor(model => model.IsDisabled.Value)         
    </div>
</div> 
25
VitalyB

Mein Modell hat einen Booleschen Wert, der nullwertfähig sein muss

Warum? Das macht keinen Sinn. Ein Kontrollkästchen hat zwei Zustände: aktiviert/nicht markiert oder wahr/falsch, wenn Sie möchten. Es gibt keinen dritten Staat. 

Oder warten Sie, bis Sie Ihre Domänenmodelle in Ihren Ansichten anstelle von Ansichtsmodellen verwenden? Das ist dein Problem. Die Lösung für mich ist also, ein Ansichtsmodell zu verwenden, in dem Sie eine einfache boolesche Eigenschaft definieren:

public class MyViewModel
{
    public bool Foo { get; set; }
}

jetzt wird Ihre Controller-Aktion dieses Ansichtsmodell an die Ansicht übergeben und das entsprechende Kontrollkästchen generieren.

14
Darin Dimitrov

Um ein Primitiv mit ausgeblendeten Feldern zu komplizieren, wird geklärt, ob Falsch oder Null nicht empfohlen wird.

Checkbox ist nicht das, was Sie verwenden sollten - es hat wirklich nur einen Status: Checked . Ansonsten könnte es alles sein. 

Wenn Ihr Datenbankfeld ein boolescher Nullwert (bool?) ist, sollte die UX 3-Optionsfelder verwenden. Dabei steht der erste Button für "Checked", der zweite Button für "Not Checked" und der dritte Button für Ihre Null, unabhängig von der Semantik von null bedeutet. Sie können eine <select><option>-Dropdown-Liste verwenden, um Immobilien zu speichern, aber der Benutzer muss zweimal klicken, und die Auswahlmöglichkeiten sind fast nicht sofort klar.

  1     0      null 
True  False  Not Set
Yes   No     Undecided
Male  Female Unknown
On    Off    Not Detected

Die RadioButtonList, definiert als eine Erweiterung mit dem Namen RadioButtonForSelectList, erstellt die Optionsfelder einschließlich des ausgewählten/geprüften Werts und legt den <div class="RBxxxx"> fest, sodass Sie die Optionsfelder mithilfe von css horizontal (Anzeige: Inline-Block), vertikal oder tabellarisch (Anzeige: Inline-Block; Breite: 100px;)

Im Modell (ich verwende string, string für die Wörterbuchdefinition als pädagogisches Beispiel. Sie können bool ?, string verwenden.)

public IEnumerable<SelectListItem> Sexsli { get; set; }
       SexDict = new Dictionary<string, string>()
        {
                { "M", "Male"},
                { "F", "Female" },
                { "U", "Undecided" },

        };

        //Convert the Dictionary Type into a SelectListItem Type
        Sexsli = SexDict.Select(k =>
              new SelectListItem
              {
                  Selected = (k.Key == "U"),
                  Text = k.Value,
                  Value = k.Key.ToString()
              });

<fieldset id="Gender">
<legend id="GenderLegend" title="Gender - Sex">I am a</legend>
    @Html.RadioButtonForSelectList(m => m.Sexsli, Model.Sexsli, "Sex") 
        @Html.ValidationMessageFor(m => m.Sexsli)
</fieldset>

public static class HtmlExtensions
{
public static MvcHtmlString RadioButtonForSelectList<TModel, TProperty>(
    this HtmlHelper<TModel> htmlHelper,
    Expression<Func<TModel, TProperty>> expression,
    IEnumerable<SelectListItem> listOfValues,
    String rbClassName = "Horizontal")
{
var metaData = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
var sb = new StringBuilder();

if (listOfValues != null)
{
    // Create a radio button for each item in the list 
    foreach (SelectListItem item in listOfValues)
    {
        // Generate an id to be given to the radio button field 
        var id = string.Format("{0}_{1}", metaData.PropertyName, item.Value);

        // Create and populate a radio button using the existing html helpers 
        var label = htmlHelper.Label(id, HttpUtility.HtmlEncode(item.Text));

        var radio = String.Empty;

        if (item.Selected == true)
        {
            radio = htmlHelper.RadioButtonFor(expression, item.Value, new { id = id, @checked = "checked" }).ToHtmlString();
        }
        else
        {
            radio = htmlHelper.RadioButtonFor(expression, item.Value, new { id = id }).ToHtmlString();

        }// Create the html string to return to client browser
        // e.g. <input data-val="true" data-val-required="You must select an option" id="RB_1" name="RB" type="radio" value="1" /><label for="RB_1">Choice 1</label> 

        sb.AppendFormat("<div class=\"RB{2}\">{0}{1}</div>", radio, label, rbClassName);
    }
}

return MvcHtmlString.Create(sb.ToString());
}
}
6
Jules Bartow

Ich würde tatsächlich eine Vorlage dafür erstellen und diese Vorlage mit einem EditorFor () verwenden.

So habe ich es gemacht:

  1. Erstellen Sie Meine Vorlage, die im Grunde genommen eine Teilansicht ist, die ich im EditorTemplates-Verzeichnis erstellt habe. Geben Sie unter Shared unter Views den Namen (zum Beispiel): CheckboxTemplate:

    @using System.Globalization    
    @using System.Web.Mvc.Html    
    @model bool?
    
    @{
        bool? myModel = false;
        if (Model.HasValue)
        {
            myModel = Model.Value;
        }
    }
    
    <input type="checkbox" checked="@(myModel)" name="@ViewData.TemplateInfo.HtmlFieldPrefix" value="True" style="width:20px;" />
    
  2. Verwenden Sie es wie folgt (in jeder Ansicht):

    @ Html.EditorFor (x => x.MyNullableBooleanCheckboxToBe, "CheckboxTemplate")

Das ist alles.

Vorlagen sind in MVC so leistungsstark, dass Sie sie verwenden können. Sie können eine ganze Seite als Vorlage erstellen, die Sie mit der Funktion @Html.EditorFor() verwenden würden. vorausgesetzt, Sie übergeben das Ansichtsmodell im Lambda-Ausdruck.

3
t_plusplus

Der sauberste Ansatz, den ich finden könnte, ist die Erweiterung der verfügbaren Erweiterungen für HtmlHelper, während die vom Framework bereitgestellten Funktionen weiterhin verwendet werden.

public static MvcHtmlString CheckBoxFor<T>(this HtmlHelper<T> htmlHelper, Expression<Func<T, bool?>> expression, IDictionary<string, object> htmlAttributes) {

    ModelMetadata modelMeta = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
    bool? value = (modelMeta.Model as bool?);

    string name = ExpressionHelper.GetExpressionText(expression);

    return htmlHelper.CheckBox(name, value ?? false, htmlAttributes);
}

Ich experimentierte mit "Formung" des Ausdrucks, um einen geraden Durchgang zum nativen CheckBoxFor<Expression<Func<T, bool>>> zu ermöglichen, aber ich denke nicht, dass dies möglich ist.

3
Red Taz

Für mich bestand die Lösung darin, das Ansichtsmodell zu ändern. Stellen Sie sich vor, Sie suchen nach Rechnungen. Diese Rechnungen können bezahlt werden oder nicht. Ihre Suche hat also drei Optionen: Bezahlt, Unbezahlt oder "Ich interessiere mich nicht".

Ich hatte das ursprünglich als Bool eingestellt? Feld:

public bool? PaidInvoices { get; set; }

Dies brachte mich dazu, auf diese Frage zu stolpern. Am Ende habe ich einen Enum-Typ erstellt und wie folgt behandelt:

@Html.RadioButtonFor(m => m.PaidInvoices, PaidStatus.NotSpecified, new { @checked = true })
@Html.RadioButtonFor(m => m.PaidInvoices, PaidStatus.Yes) 
@Html.RadioButtonFor(m => m.PaidInvoices, PaidStatus.No)

Natürlich habe ich sie in Etiketten verpackt und habe Text spezifiziert.

3
Paul

Checkbox bietet Ihnen nur 2 Werte (true, false). Nullable boolean hat 3 Werte (true, false, null), daher ist es unmöglich, dies mit einem Kontrollkästchen zu tun.

Eine gute Option ist die Verwendung eines Dropdown-Menüs.

Modell

public bool? myValue;
public List<SelectListItem> valueList;

Regler

model.valueList = new List<SelectListItem>();
model.valueList.Add(new SelectListItem() { Text = "", Value = "" });
model.valueList.Add(new SelectListItem() { Text = "Yes", Value = "true" });
model.valueList.Add(new SelectListItem() { Text = "No", Value = "false" });

Aussicht

@Html.DropDownListFor(m => m.myValue, valueList)
3
Gudradain

Ich hatte in der Vergangenheit ein ähnliches Problem. 

Erstellen Sie eine Checkbox-Eingabe in HTML, und legen Sie das Attribut name = "Foo" fest. Dies sollte dennoch ordnungsgemäß veröffentlicht werden. 

<input type="checkbox" name="Foo" checked="@model.Foo.Value" /> Foo Checkbox<br />
1
Chris Lucian

Wenn Sie ein EditorTemplate für ein Modell erstellen, das ein nullfähiges Bool enthält ...

  • Teile den nullwertfähigen Bool in 2 Booleans auf:

    // Foo is still a nullable boolean.
    public bool? Foo 
    {
        get 
        { 
            if (FooIsNull)
                return null;
    
            return FooCheckbox;  
        }
        set
        {
            FooIsNull   = (value == null);
            FooCheckbox = (value ?? false);
        }
    }
    
    // These contain the value of Foo. Public only so they are visible in Razor views.
    public bool FooIsNull { get; set; }
    public bool FooCheckbox { get; set; }
    
  • Innerhalb der Editorvorlage:

    @Html.HiddenFor(m => m.FooIsNull)
    
    @if (Model.FooIsNull)
    {
        // Null means "checkbox is hidden"
        @Html.HiddenFor(m => m.FooCheckbox)
    }
    else
    {
        @Html.CheckBoxFor(m => m.FooCheckbox)
    }
    
  • Postback der ursprünglichen Eigenschaft Foo nicht, da diese nun aus FooIsNull und FooCheckbox berechnet wird.

0
user1023602

Erweiterungsmethoden:

        public static MvcHtmlString CheckBoxFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, bool?>> expression)
        {
            return htmlHelper.CheckBoxFor<TModel>(expression, null);
        }
        public static MvcHtmlString CheckBoxFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, bool?>> expression, object htmlAttributes)
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            bool? isChecked = null;
            if (metadata.Model != null)
            {
                bool modelChecked;
                if (Boolean.TryParse(metadata.Model.ToString(), out modelChecked))
                {
                    isChecked = modelChecked;
                }
            }
            return htmlHelper.CheckBox(ExpressionHelper.GetExpressionText(expression), isChecked??false ,  htmlAttributes);
        }
0
Jim

Ich stand auch vor demselben Problem. Ich habe den folgenden Ansatz ausprobiert, um das Problem zu beheben.

@{

   bool testVar = (Model.MYVar ? true : false);

 }

<label>@Html.CheckBoxFor(m => testVar)testVar</label><br />
0
Amit Kumar

Alle oben genannten Antworten enthielten eigene Probleme. Die einfachste/sauberste Art, IMO zu erstellen, besteht darin, einen Helfer zu erstellen

MVC5 Rasierer

App_Code/Helpers.cshtml

@helper CheckBoxFor(WebViewPage page, string propertyName, bool? value, string htmlAttributes = null)
{
    if (value == null)
    {
        <div class="checkbox-nullable">
            <input type="checkbox" @page.Html.Raw(htmlAttributes)>
        </div>
    }
    else if (value == true)
    {
        <input type="checkbox" value="true" @page.Html.Raw(htmlAttributes) checked>
    }
    else
    {
        <input type="checkbox" value="false" @page.Html.Raw(htmlAttributes)>
    }
}

Verwendungszweck

@Helpers.CheckBoxFor(this, "IsPaymentRecordOk", Model.IsPaymentRecordOk)

In meinem Szenario bedeutet ein mit Null belegbares Ankreuzfeld, dass ein Mitarbeiter die Frage noch nicht an den Client gestellt hat. Er ist also in einen .checkbox-nullable eingeschlossen, sodass Sie den Stil entsprechend anpassen können und dem Endbenutzer dabei helfen können, festzustellen, dass es sich weder um true noch false handelt.

CSS

.checkbox-nullable {
    border: 1px solid red;
    padding: 3px;
    display: inline-block;
}
0
zanderwar

Suchen Sie einfach nach dem Nullwert und geben Sie false zurück:

@{ bool nullableValue = ((Model.nullableValue == null) || (Model.nullableValue == false)) ? false : true; }
@Html.CheckBoxFor(model => nullableValue)
0
Rodrigo Boratto