การรับค่า Checkbox ใน ASP.NET MVC 4


122

ฉันกำลังทำงานกับแอป ASP.NET MVC 4 แอพนี้มีรูปแบบพื้นฐาน แบบจำลองสำหรับแบบฟอร์มของฉันมีลักษณะดังต่อไปนี้:

public class MyModel
{
    public string Name { get; set; }
    public bool Remember { get; set; }
}

ในรูปแบบของฉันฉันมี HTML ต่อไปนี้

<input id="Name" name="Name" type="text" value="@Model.Name" />
<input id="Remember" name="Remember" type="checkbox" value="@Model.Remember" />
<label for="Remember">&nbsp;Remember Me?</label>

เมื่อฉันโพสต์แบบฟอร์มค่าจดจำในโมเดลจะเป็นเท็จเสมอ อย่างไรก็ตามคุณสมบัติ Name ในโมเดลมีค่า ฉันได้ทดสอบโดยตั้งค่าเบรกพอยต์ดังต่อไปนี้:

[HttpPost]
public ActionResult MyAction(MyModel model)
{
  Console.WriteLine(model.Remember.ToString());
}

ฉันคิดไม่ออก เหตุใดจึงไม่ตั้งค่า Checkbox


มีการโพสต์ด้วยค่าที่เหมาะสมหรือไม่? ตรวจสอบได้ไหมว่าใช้มือไม่พาย นอกจากนี้ฉันไม่ทราบว่าค่าของช่องทำเครื่องหมายแปลเป็นบูลหรือไม่
shahkalpesh

สิ่งนี้จะโพสต์เป็น "เปิด" หรือ "ปิด" ในแบบฟอร์ม เห็นได้ชัดว่าสิ่งนี้ไม่ผูกมัดอย่างถูกต้อง ฉันทำ enum โง่เพื่อหลีกเลี่ยงสิ่งนี้
Yablargo

@Yablargo คุณไม่จำเป็นต้อง enum เพียงเพิ่มค่า = "true" ให้กับแท็กอินพุต และใช้ hidden with value = "false" ดังที่แสดงด้านล่าง
sympatric greg

คำตอบ:


213
@Html.EditorFor(x => x.Remember)

จะสร้าง:

<input id="Remember" type="checkbox" value="true" name="Remember" />
<input type="hidden" value="false" name="Remember" />

มันทำงานอย่างไร:

  • หากcheckboxยังคงไม่เลือกแบบฟอร์มจะส่งเฉพาะhiddenค่า (เท็จ)
  • หากเลือกแล้วฟอร์มจะส่งสองฟิลด์ (เท็จและจริง) และชุด MVC trueสำหรับboolคุณสมบัติของโมเดล

<input id="Remember" name="Remember" type="checkbox" value="@Model.Remember" />

สิ่งนี้จะส่งค่าเริ่มต้นเสมอหากเลือก


7
สวัสดีพฤติกรรมนี้ทำให้โมเดลของฉันล้มเหลวในการตรวจสอบความถูกต้องเนื่องจากดูเหมือนจะไม่สามารถหาวิธีเปลี่ยน [จริงเท็จ] ให้เป็นค่าบูลีนเดียวได้ คุณจะแก้ไขปัญหานี้อย่างไร?
Obi

@ObiOnuorah ใช้ก่อสร้างอะไรคะ? ตัวช่วยหรือมาร์กอัป html แบบฮาร์ดโค้ด?
webdeveloper

5
Html.EditorFor หรือ Html.CheckBoxFor อย่างใดอย่างหนึ่งให้ผลลัพธ์เดียวกัน
โอบี

3
หากใช้ formCollection สตริงที่ส่งคืนสำหรับช่องทำเครื่องหมายผลลัพธ์คือ: "true, false" คุณวิเคราะห์สิ่งนี้อย่างไร? Replace () เป็นตัวเลือกเดียวหรือไม่?
Jo Smo

7
หากคุณกำลังเพิ่มช่องทำเครื่องหมายของคุณเองด้วยตนเองแล้วส่วนหนึ่งที่สำคัญคือค่าควรตั้งค่าเป็น"จริง"มิฉะนั้นค่าเริ่มต้นกลับโดยรูปแบบจะเป็น"กับ"และ "กับ" ไม่สามารถจะผูกพันกับบูล ซึ่งต้องการจริง / เท็จ (คุณอาจเห็นข้อผิดพลาดในการตรวจสอบความถูกต้องว่าค่า "เปิด" ไม่ถูกต้องสำหรับฟิลด์ )
Greg

69

เนื่องจากคุณใช้ Model.Name เพื่อตั้งค่า ฉันถือว่าคุณกำลังส่งโมเดลมุมมองที่ว่างเปล่าไปยัง View

ดังนั้นค่าสำหรับ Remember จึงเป็นเท็จและตั้งค่าบนองค์ประกอบช่องทำเครื่องหมายเป็นเท็จ ซึ่งหมายความว่าเมื่อคุณเลือกช่องทำเครื่องหมายแสดงว่าคุณกำลังโพสต์ค่า "เท็จ" ด้วยแบบฟอร์ม เมื่อคุณไม่ได้เลือกมันจะไม่ถูกโพสต์ดังนั้นโมเดลจึงมีค่าเริ่มต้นเป็นเท็จ ซึ่งเป็นสาเหตุที่คุณเห็นค่าผิดพลาดในทั้งสองกรณี

ค่าจะถูกส่งผ่านเมื่อคุณทำเครื่องหมายในช่องเลือกเท่านั้น ในการทำช่องทำเครื่องหมายใน Mvc ให้ใช้

@Html.CheckBoxFor(x => x.Remember)

หรือหากคุณไม่ต้องการผูกโมเดลเข้ากับมุมมอง

@Html.CheckBox("Remember")

Mvc ใช้เวทมนตร์กับฟิลด์ที่ซ่อนอยู่เพื่อคงค่าเมื่อไม่ได้เลือก

แก้ไขหากคุณมีความเกลียดชังที่จะทำเช่นนั้นและต้องการสร้างองค์ประกอบด้วยตัวคุณเองคุณสามารถทำได้

<input id="Remember" name="Remember" type="checkbox" value="true" @(Model.Remember ? "checked=\"checked\"" : "") />

2
@Html.CheckboxForรหัสจริงควรจะเป็น@Html.CheckBoxFor
fujiiface

คุณจะใช้@(Model.Remember ? "checked=\"checked\"" : "")ปุ่มตัวเลือกอย่างไร? หรือว่าเป็นไปไม่ได้
Izzy

ด้วยตัวเลือกที่คุณเป็นเพียงการจัดการ HTML โดยตรงปุ่มเป็นเพียงtype="radio"และการเลือกหนึ่งที่คุณต้องการเลือกใน HTML checked="checked"เป็นเช่นเดียวกับข้างต้น ความแตกต่างคือคุณจะมี<input />องค์ประกอบหลายอย่างที่มีชื่อเดียวกัน คุณต้องพิจารณาว่าจะใช้ HTML เสริมกับอันใด
Dan Saltmer

@Html.CheckBoxFor(x => x.Remember)สิ่งนี้ได้ผลสำหรับฉัน
JustLearning

15

ใช้แค่นี้

$("input[type=checkbox]").change(function () {
    if ($(this).prop("checked")) {
        $(this).val(true);
    } else {
        $(this).val(false);
    }
});

หรือ:$(this).val($(this).is(":checked"));
Norman

5

แทน

 <input id="Remember" name="Remember" type="checkbox" value="@Model.Remember" />

ใช้:

 @Html.EditorFor(x => x.Remember)

ซึ่งจะทำให้คุณมีช่องทำเครื่องหมายสำหรับจดจำโดยเฉพาะ


4

โอเคช่องทำเครื่องหมายแปลกไปหน่อย เมื่อคุณใช้ตัวช่วย Html จะสร้างอินพุตช่องทำเครื่องหมายสองช่องบนมาร์กอัปและทั้งสองจะถูกส่งผ่านเป็นคู่ค่าชื่อ - ค่าของ IEnumerable หากมีการเลือก

หากไม่ได้ตรวจสอบมาร์กอัปจะถูกส่งผ่านเฉพาะอินพุตที่ซ่อนอยู่ซึ่งมีค่าเป็นเท็จ

ตัวอย่างเช่นในมาร์กอัปที่คุณมี:

      @Html.CheckBox("Chbxs") 

และในการดำเนินการของคอนโทรลเลอร์ (ตรวจสอบให้แน่ใจว่าชื่อตรงกับชื่อพารามิเตอร์ของช่องทำเครื่องหมายบนคอนโทรลเลอร์):

      public ActionResult Index(string param1, string param2,
      string param3, IEnumerable<bool> Chbxs)

จากนั้นในคอนโทรลเลอร์คุณสามารถทำสิ่งต่างๆเช่น:

      if (Chbxs != null && Chbxs.Count() == 2)
        {
            checkBoxOnMarkup = true;
        }
        else
        {
            checkBoxOnMarkup = false;
        }

ฉันรู้ว่านี่ไม่ใช่วิธีแก้ปัญหาที่หรูหรา หวังว่าใครบางคนที่นี่สามารถให้คำแนะนำได้


3

ในการแปลงค่าที่ส่งคืนจากกล่องกาเครื่องหมายในรูปแบบเป็นคุณสมบัติบูลีนฉันใช้ ValueProviderResult ในตัวแปลงบิลด์ใน ModelBinder ที่กำหนดเอง

ValueProviderResult cbValue = bindingContext.ValueProvider.GetValue("CheckBoxName");
bool value = (bool)cbValue.ConvertTo(typeof(bool));


2

ฉันพบปัญหาที่คล้ายกันและสามารถรับค่าช่องทำเครื่องหมายกลับมาได้โดยใช้ช่องทำเครื่องหมาย hiddenfor และ JQuery เล็กน้อยดังนี้:

@Html.CheckBox("isPreferred", Model.IsPreferred)
@Html.HiddenFor(m => m.IsPreferred)

<script>

    $("#isPreferred").change(function () {

        $("#IsPreferred").val($("#isPreferred").val());

    })

</script>

2

นี่เป็นความเจ็บปวดครั้งใหญ่และรู้สึกว่ามันควรจะง่ายกว่านี้ นี่คือการตั้งค่าและวิธีแก้ปัญหาของฉัน

ฉันใช้ตัวช่วย HTML ต่อไปนี้:

@Html.CheckBoxFor(model => model.ActiveFlag)

จากนั้นในตัวควบคุมฉันกำลังตรวจสอบการรวบรวมและประมวลผลแบบฟอร์ม:

bool activeFlag = collection["ActiveFlag"] == "false" ? false : true;
[modelObject].ActiveFlag = activeFlag;

เห็นด้วยฉันทำให้สิ่งนี้สั้นลงกว่าเดิมเพราะuser.IsActive = fc["IsActive"] != "false";ฉันยังรู้สึกสกปรกในการเปรียบเทียบสตริงกับมัน
WildJoe

1

ฉันเพิ่งเจอสิ่งนี้ (ฉันไม่อยากเชื่อเลยว่ามันจะไม่ผูกเปิด / ปิด!)

อย่างไรก็ตาม!

<input type="checkbox" name="checked" />

จะโพสต์ค่าเป็น "เปิด" หรือ "ปิด"

WONTนี้เชื่อมโยงกับบูลีน แต่คุณสามารถแก้ปัญหาโง่ ๆ นี้ได้!

 public class MyViewModel
 {
     /// <summary>
     /// This is a really dumb hack, because the form post sends "on" / "off"
     /// </summary>                    
     public enum Checkbox
     {
        on = 1,
        off = 0
     }
     public string Name { get; set; }
     public Checkbox Checked { get; set; }
}

1
@Html.EditorFor(x => x.ShowComment)


$(function () {
        // set default value to control on document ready instead of 'on'/'off' 
        $("input[type='checkbox'][name='ShowComment']").val(@Model.ShowComment.ToString().ToLower());
    });

    $("#ShowComment").change(function() {
        // this block sets value to checkbox control for "true" / "false"

        var chkVal = $("input[type='checkbox'][name='ShowComment']").val();
        if (chkVal == 'false') $("input[type='checkbox'][name='ShowComment']").val(true);
        else $("input[type='checkbox'][name='ShowComment']").val(false);

    });

3
สวัสดี Surendran และยินดีต้อนรับสู่ Stack Overflow เมื่อคุณใส่รหัสโปรดจัดรูปแบบเพื่อให้อ่านง่าย แต่ที่สำคัญกว่านั้นสิ่งสำคัญคือต้องอธิบายว่าเหตุใดรหัสที่รวมอยู่จึงตอบคำถามของ OP
Alex A.

1

สำหรับ MVC โดยใช้ Model รุ่น:

public class UserInfo
{
    public string UserID { get; set; }
    public string UserName { get; set; }
    public string Password { get; set; }
    public bool RememberMe { get; set; }
}

HTML:

<input type="checkbox" value="true" id="checkbox1" name="RememberMe" checked="@Model.RememberMe"/>
<label for="checkbox1"></label>

ในฟังก์ชัน [HttpPost] เราจะได้รับคุณสมบัติ

[HttpPost]
public ActionResult Login(UserInfo user)
{
   //...
   return View(user);
}

1

หากคุณต้องการใช้ HTML ธรรมดา (ไม่ว่าด้วยเหตุผลใดก็ตาม) และไม่ใช่ส่วนขยาย HtmlHelper ในตัวคุณสามารถทำได้ด้วยวิธีนี้

แทน

<input id="Remember" name="Remember" type="checkbox" value="@Model.Remember" />

ลองใช้

<input id="Remember" name="Remember" type="checkbox" value="true" @(Model.Remember ? "checked" : "") />

อินพุตช่องทำเครื่องหมายใน HTML ทำงานดังนั้นเมื่อตรวจสอบแล้วพวกเขาจะส่งค่าและเมื่อไม่ได้ตรวจสอบจะไม่ส่งอะไรเลย (ซึ่งจะทำให้ ASP.NET MVC เปลี่ยนกลับเป็นค่าเริ่มต้นของ ฟิลด์false) นอกจากนี้ค่าของช่องทำเครื่องหมายใน HTML อาจเป็นอะไรก็ได้ที่ไม่ใช่แค่จริง / เท็จดังนั้นหากคุณต้องการจริงๆคุณสามารถใช้ช่องทำเครื่องหมายสำหรับฟิลด์สตริงในโมเดลของคุณได้

หากคุณใช้อินHtml.RenderCheckboxพุทในตัวมันจะส่งออกอินพุตสองช่อง: ช่องทำเครื่องหมายและช่องที่ซ่อนอยู่เพื่อให้ส่งค่าเท็จเมื่อไม่ได้เลือกช่องทำเครื่องหมาย (ไม่ใช่แค่ไม่มีอะไร) ซึ่งอาจทำให้เกิดสถานการณ์ที่ไม่คาดคิดเช่นนี้:


0

สำหรับช่องทำเครื่องหมายหลายช่องที่มีชื่อเดียวกัน ... รหัสเพื่อลบเท็จที่ไม่จำเป็น:

List<string> d_taxe1 = new List<string>(Request.Form.GetValues("taxe1"));
d_taxe1 = form_checkbox.RemoveExtraFalseFromCheckbox(d_taxe1);

ฟังก์ชัน

public class form_checkbox
{

    public static List<string> RemoveExtraFalseFromCheckbox(List<string> val)
    {
        List<string> d_taxe1_list = new List<string>(val);

        int y = 0;

        foreach (string cbox in val)
        {

            if (val[y] == "false")
            {
                if (y > 0)
                {
                    if (val[y - 1] == "true")
                    {
                        d_taxe1_list[y] = "remove";
                    }
                }

            }

            y++;
        }

        val = new List<string>(d_taxe1_list);

        foreach (var del in d_taxe1_list)
            if (del == "remove") val.Remove(del);

        return val;

    }      



}

ใช้มัน :

int x = 0;
foreach (var detail in d_prix){
factured.taxe1 = (d_taxe1[x] == "true") ? true : false;
x++;
}

0
public ActionResult Index(string username, string password, string rememberMe)
{
   if (!string.IsNullOrEmpty(username))
   {
      bool remember = bool.Parse(rememberMe);
      //...
   }
   return View();
}

0

Modify Remember เป็นแบบนี้

public class MyModel
{
    public string Name { get; set; }
    public bool? Remember { get; set; }
}

ใช้บูลที่เป็นโมฆะในตัวควบคุมและทางเลือกกลับเป็นเท็จในค่าว่างเช่นนี้

[HttpPost]
public ActionResult MyAction(MyModel model)
{
    model.Remember = model.Remember ?? false;
    Console.WriteLine(model.Remember.ToString());
}

0

ในกรณีของฉันฉันไม่ได้ตั้งค่าคุณสมบัติของโมเดล "จดจำ" ในเมธอด get ตรวจสอบตรรกะของคุณในคอนโทรลเลอร์ คุณอาจจะทำเช่นเดียวกัน ฉันหวังว่านี่จะช่วยได้!


0

ฉันอ่านคำตอบอื่น ๆ และไม่ค่อยได้ผล - ดังนั้นนี่คือคำตอบที่ฉันลงเอยด้วย

แบบฟอร์มของฉันใช้Html.EditorFor(e => e.Property)เพื่อสร้างช่องทำเครื่องหมายและใช้FormCollectionในคอนโทรลเลอร์ซึ่งจะส่งผ่านค่าสตริงของ'true,false'ในคอนโทรลเลอร์

เมื่อฉันจัดการผลลัพธ์ฉันใช้การวนรอบเพื่อวนรอบ - ฉันยังใช้InfoPropertyอินสแตนซ์เพื่อแสดงมูลค่าโมเดลปัจจุบันที่ประเมินจากแบบฟอร์ม

ดังนั้นฉันจึงตรวจสอบว่าสตริงที่ส่งคืนเริ่มต้นด้วยคำ'true'นั้นแทนหรือไม่จากนั้นตั้งค่าตัวแปรบูลีนtrueและส่งผ่านไปยังโมเดลการส่งคืน

if (KeyName.EndsWith("OnOff"))
{
    // set on/off flags value to the model instance
    bool keyTrueFalse = false;
    if(values[KeyName].StartsWith("true"))
    {
        keyTrueFalse = true;
    }
    infoProperty.SetValue(processedInfo, keyTrueFalse);
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.