MVC Razor ดูแบบจำลองของ foreach ที่ซ้อนกัน


94

ลองนึกภาพสถานการณ์ทั่วไปนี่เป็นเวอร์ชันที่ง่ายกว่าของสิ่งที่ฉันเจอ ที่จริงฉันมีสองชั้นที่ทำรังอยู่บนของฉัน ....

แต่นี่คือสถานการณ์

ชุดรูปแบบประกอบด้วยประเภทรายการประกอบด้วย List Product มีรายการ

ตัวควบคุมของฉันมีธีมที่ได้รับการเติมเต็มพร้อมด้วยหมวดหมู่ทั้งหมดสำหรับธีมนั้นผลิตภัณฑ์ในหมวดหมู่นี้และคำสั่งซื้อของพวกเขา

คอลเลกชันคำสั่งซื้อมีคุณสมบัติที่เรียกว่า Quantity (ท่ามกลางอื่น ๆ อีกมากมาย) ที่ต้องแก้ไขได้

@model ViewModels.MyViewModels.Theme

@Html.LabelFor(Model.Theme.name)
@foreach (var category in Model.Theme)
{
   @Html.LabelFor(category.name)
   @foreach(var product in theme.Products)
   {
      @Html.LabelFor(product.name)
      @foreach(var order in product.Orders)
      {
          @Html.TextBoxFor(order.Quantity)
          @Html.TextAreaFor(order.Note)
          @Html.EditorFor(order.DateRequestedDeliveryFor)
      }
   }
}

ถ้าฉันใช้แลมด้าแทนดูเหมือนว่าฉันจะได้รับการอ้างอิงไปยังวัตถุโมเดลด้านบนเท่านั้น "ธีม" ไม่ใช่สิ่งที่อยู่ในลูป foreach

สิ่งที่ฉันพยายามทำนั้นเป็นไปได้หรือไม่หรือฉันประเมินค่าเกินหรือเข้าใจผิดว่าเป็นไปได้หรือไม่

จากข้างต้นฉันได้รับข้อผิดพลาดใน TextboxFor, EditorFor ฯลฯ

CS0411: อาร์กิวเมนต์ประเภทสำหรับเมธอด 'System.Web.Mvc.Html.InputExtensions.TextBoxFor (System.Web.Mvc.HtmlHelper, System.Linq.Expressions.Expression>)' ไม่สามารถอนุมานได้จากการใช้งาน ลองระบุประเภทอาร์กิวเมนต์อย่างชัดเจน

ขอบคุณ.


1
คุณไม่ควรมี@ก่อนทั้งหมดforeach? คุณไม่ควรมี lambdas ในHtml.EditorFor( Html.EditorFor(m => m.Note)เช่น) และวิธีการอื่น ๆ หรือไม่? ฉันอาจเข้าใจผิด แต่คุณช่วยวางรหัสจริงของคุณได้ไหม ฉันค่อนข้างใหม่กับ MVC แต่คุณสามารถแก้ไขได้ค่อนข้างง่ายด้วยมุมมองบางส่วนหรือบรรณาธิการ (ถ้าเป็นชื่อ?)
Kobi

category.nameฉันแน่ใจว่าเป็นstringและ...Forไม่รองรับสตริงเป็นพารามิเตอร์แรก
balexandre

ใช่ฉันพลาด @ ที่เพิ่มในตอนนี้ ขอบคุณ. อย่างไรก็ตามสำหรับ lambda ถ้าฉันเริ่มพิมพ์ @ Html.TextBoxFor (m => m. ดูเหมือนว่าฉันจะได้รับการอ้างอิงถึงวัตถุ Model ด้านบนเท่านั้นไม่ใช่สิ่งที่อยู่ใน foreach loop
David C

@DavidC - ฉันไม่รู้จักพอของ MVC 3 ที่จะตอบยัง - :)แต่ผมสงสัยว่าเป็นปัญหาของคุณ
Kobi

2
ฉันอยู่บนรถไฟ แต่ถ้ายังไม่ได้รับคำตอบเมื่อถึงเวลาทำงานก็โพสต์คำตอบได้ คำตอบอย่างรวดเร็วคือการใช้แบบปกติfor()แทนที่จะเป็นforeachไฟล์. ฉันจะอธิบายว่าทำไมทำให้มันสับสนกับฉันมานานแล้วด้วย
J.Holmes

คำตอบ:


304

คำตอบอย่างรวดเร็วคือการใช้for()ห่วงในสถานที่ของคุณforeach()ลูป สิ่งที่ต้องการ:

@for(var themeIndex = 0; themeIndex < Model.Theme.Count(); themeIndex++)
{
   @Html.LabelFor(model => model.Theme[themeIndex])

   @for(var productIndex=0; productIndex < Model.Theme[themeIndex].Products.Count(); productIndex++)
   {
      @Html.LabelFor(model=>model.Theme[themeIndex].Products[productIndex].name)
      @for(var orderIndex=0; orderIndex < Model.Theme[themeIndex].Products[productIndex].Orders; orderIndex++)
      {
          @Html.TextBoxFor(model => model.Theme[themeIndex].Products[productIndex].Orders[orderIndex].Quantity)
          @Html.TextAreaFor(model => model.Theme[themeIndex].Products[productIndex].Orders[orderIndex].Note)
          @Html.EditorFor(model => model.Theme[themeIndex].Products[productIndex].Orders[orderIndex].DateRequestedDeliveryFor)
      }
   }
}

แต่สิ่งนี้ทำให้เข้าใจได้ว่าเหตุใดจึงแก้ไขปัญหาได้

มีสามสิ่งที่คุณมีความเข้าใจคร่าวๆก่อนที่จะแก้ไขปัญหานี้ได้ ฉันต้องยอมรับว่าฉันได้รับลัทธินี้มานานแล้วเมื่อฉันเริ่มทำงานกับเฟรมเวิร์ก และใช้เวลาพอสมควรในการทำความเข้าใจกับสิ่งที่เกิดขึ้น

ทั้งสามสิ่งคือ:

  • วิธีทำLabelForและอื่น ๆ ที่...Forผู้ช่วยทำงานใน MVC?
  • Expression Tree คืออะไร?
  • Model Binder ทำงานอย่างไร?

แนวคิดทั้งสามนี้เชื่อมโยงกันเพื่อให้ได้คำตอบ

วิธีทำLabelForและอื่น ๆ ที่...Forผู้ช่วยทำงานใน MVC?

ดังนั้นคุณได้ใช้HtmlHelper<T>ส่วนขยายสำหรับLabelForและTextBoxForและอื่น ๆ และคุณอาจสังเกตเห็นว่าเมื่อคุณเรียกใช้พวกเขาคุณส่งแลมบ์ดาและสร้าง html ขึ้นมาอย่างน่าอัศจรรย์ แต่อย่างไร?

ดังนั้นสิ่งแรกที่ต้องสังเกตคือลายเซ็นสำหรับตัวช่วยเหล่านี้ มาดูการโอเวอร์โหลดที่ง่ายที่สุดสำหรับ TextBoxFor

public static MvcHtmlString TextBoxFor<TModel, TProperty>(
    this HtmlHelper<TModel> htmlHelper,
    Expression<Func<TModel, TProperty>> expression
) 

ขั้นแรกนี่เป็นวิธีการขยายสำหรับHtmlHelperประเภทที่พิมพ์<TModel>มากเกินไป ดังนั้นเพื่อระบุสิ่งที่เกิดขึ้นเบื้องหลังเมื่อมีดโกนแสดงมุมมองนี้มันจะสร้างคลาส ภายในคลาสนี้เป็นอินสแตนซ์ของHtmlHelper<TModel>(เป็นคุณสมบัติHtmlซึ่งเป็นเหตุผลที่คุณสามารถใช้ได้@Html...) TModelประเภทที่กำหนดไว้ใน@modelคำสั่งของคุณอยู่ที่ไหน ดังนั้นในกรณีของคุณเมื่อคุณดูมุมมองนี้TModel จะเป็นประเภทViewModels.MyViewModels.Themeเสมอ

ตอนนี้การโต้เถียงครั้งต่อไปค่อนข้างยุ่งยาก ดังนั้นมาดูคำวิงวอน

@Html.TextBoxFor(model=>model.SomeProperty);

ดูเหมือนว่าเรามีแลมด้าตัวเล็ก ๆ และถ้ามีใครจะเดาลายเซ็นเราอาจคิดว่าประเภทของอาร์กิวเมนต์นี้จะเป็น a ประเภทของโมเดลมุมมองFunc<TModel, TProperty>อยู่ที่ไหนTModelและTProperty อนุมานเป็นประเภทของคุณสมบัติ

แต่ thats ไม่ถูกต้องถ้าคุณมองไปที่เกิดขึ้นจริงExpression<Func<TModel, TProperty>>ประเภทของการโต้แย้งของมัน

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

อย่างไรก็ตามเมื่อคอมไพเลอร์เห็นว่า type เป็น an Expression<>มันจะไม่รวบรวม lambda ลงไปที่ MSIL ในทันที แต่มันจะสร้าง Expression Tree ขึ้นมาแทน!

คืออะไรExpression ต้นไม้ ?

ดังนั้นสิ่งที่ห่าคือต้นไม้แสดงออก ไม่ซับซ้อน แต่ก็ไม่ได้เดินเล่นในสวนสาธารณะเช่นกัน ในการอ้างถึง MS:

| แผนภูมินิพจน์แทนรหัสในโครงสร้างข้อมูลแบบต้นไม้โดยที่แต่ละโหนดเป็นนิพจน์ตัวอย่างเช่นการเรียกใช้เมธอดหรือการดำเนินการไบนารีเช่น x <y

พูดง่ายๆก็คือต้นไม้นิพจน์คือการแสดงฟังก์ชันเป็นชุดของ "การกระทำ"

ในกรณีของmodel=>model.SomePropertyโครงสร้างนิพจน์จะมีโหนดอยู่ในนั้นซึ่งระบุว่า: "Get 'Some Property' from a 'model'"

แผนภูมินิพจน์นี้สามารถรวบรวมเป็นฟังก์ชันที่สามารถเรียกใช้งานได้ แต่ตราบใดที่เป็นโครงสร้างนิพจน์จะเป็นเพียงชุดของโหนด

แล้วมันดีสำหรับอะไร?

ดังนั้นFunc<>หรือAction<>เมื่อคุณมีแล้วพวกมันก็เป็นปรมาณู สิ่งที่คุณทำได้ก็คือInvoke()พวกเขาหรือที่เรียกว่าบอกให้พวกเขาทำงานที่ควรจะทำ

Expression<Func<>>ในทางกลับกันแสดงถึงชุดของการกระทำซึ่งสามารถต่อท้ายจัดการเยี่ยมชมหรือรวบรวมและเรียกใช้

ทำไมคุณถึงบอกฉันทั้งหมดนี้?

ดังนั้นด้วยความเข้าใจว่าExpression<>คืออะไรเราสามารถย้อนกลับไปHtml.TextBoxForได้ เมื่อแสดงผลกล่องข้อความจำเป็นต้องสร้างบางสิ่งเกี่ยวกับคุณสมบัติที่คุณมอบให้ สิ่งที่ต้องการattributesในสถานที่สำหรับการตรวจสอบและโดยเฉพาะในกรณีนี้จะต้องคิดออกว่าจะตั้งชื่อ<input>แท็ก

ทำได้โดยการ "เดิน" ต้นไม้นิพจน์และสร้างชื่อ ดังนั้นสำหรับการแสดงออกเช่นนั้นก็เดินแสดงออกรวบรวมคุณสมบัติที่คุณจะขอและสร้างmodel=>model.SomeProperty<input name='SomeProperty'>

สำหรับตัวอย่างที่ซับซ้อนมากขึ้นเช่นmodel=>model.Foo.Bar.Baz.FooBarอาจสร้าง<input name="Foo.Bar.Baz.FooBar" value="[whatever FooBar is]" />

เข้าท่า? มันไม่ได้เป็นเพียงการทำงานว่าFunc<>ไม่ แต่วิธีการมันไม่ทำงานมันเป็นสิ่งสำคัญที่นี่

(โปรดสังเกตว่ากรอบงานอื่น ๆ เช่น LINQ ถึง SQL ทำสิ่งที่คล้ายกันโดยการเดินแผนภูมินิพจน์และสร้างไวยากรณ์ที่แตกต่างกันซึ่งในกรณีนี้คือแบบสอบถาม SQL)

Model Binder ทำงานอย่างไร?

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

ดังนั้นหากโพสต์แบบฟอร์มดูเหมือน

Foo.Bar.Baz.FooBar = Hello

และคุณกำลังโพสต์ไปยังโมเดลที่เรียกว่าSomeViewModelจากนั้นมันจะกลับกันสิ่งที่ผู้ช่วยเหลือทำในตอนแรก มันมองหาอสังหาริมทรัพย์ที่เรียกว่า "Foo" จากนั้นมองหาอสังหาริมทรัพย์ที่เรียกว่า "บาร์" จาก "Foo" จากนั้นมองหา "Baz" ... และอื่น ๆ ...

ในที่สุดก็พยายามแยกวิเคราะห์ค่าเป็นประเภท "FooBar" และกำหนดให้ "FooBar"

วุ้ย!!!

และ voila คุณมีแบบจำลองของคุณ อินสแตนซ์ Model Binder ที่เพิ่งสร้างจะถูกส่งไปยัง Action ที่ร้องขอ


ดังนั้นวิธีแก้ปัญหาของคุณจึงไม่ได้ผลเนื่องจากHtml.[Type]For()ผู้ช่วยเหลือต้องการการแสดงออก และคุณแค่ให้คุณค่าแก่พวกเขา ไม่มีความคิดว่าบริบทสำหรับค่านั้นคืออะไรและไม่รู้ว่าจะทำอย่างไรกับมัน

ตอนนี้มีบางคนแนะนำให้ใช้บางส่วนเพื่อแสดงผล ตอนนี้ในทางทฤษฎีจะได้ผล แต่อาจไม่ใช่วิธีที่คุณคาดหวัง เมื่อคุณแสดงผลบางส่วนคุณกำลังเปลี่ยนประเภทTModelเนื่องจากคุณอยู่ในบริบทมุมมองที่แตกต่างกัน ซึ่งหมายความว่าคุณสามารถอธิบายคุณสมบัติของคุณด้วยสำนวนสั้น ๆ นอกจากนี้ยังหมายความว่าเมื่อผู้ช่วยเหลือสร้างชื่อสำหรับการแสดงออกของคุณมันจะตื้น จะสร้างตามนิพจน์ที่กำหนดเท่านั้น (ไม่ใช่บริบททั้งหมด)

สมมติว่าคุณมีบางส่วนที่แสดงเพียง "Baz" (จากตัวอย่างก่อนหน้านี้) ภายในบางส่วนคุณสามารถพูดได้ว่า:

@Html.TextBoxFor(model=>model.FooBar)

ค่อนข้างมากกว่า

@Html.TextBoxFor(model=>model.Foo.Bar.Baz.FooBar)

นั่นหมายความว่าจะสร้างแท็กอินพุตดังนี้:

<input name="FooBar" />

ซึ่งถ้าคุณกำลังโพสต์แบบฟอร์มนี้เพื่อการดำเนินการที่คาดว่าจะมีขนาดใหญ่ซ้อนกันอย่างลึกซึ้ง ViewModel แล้วก็จะพยายามให้ความชุ่มชื้นคุณสมบัติที่เรียกว่าออกจากFooBar TModelสิ่งที่ดีที่สุดไม่มีอยู่ที่นั่นและที่แย่ที่สุดคืออย่างอื่นทั้งหมด หากคุณกำลังโพสต์ไปยังการดำเนินการเฉพาะที่ยอมรับ a Bazแทนที่จะเป็นรูปแบบรูทสิ่งนี้จะได้ผลดี! ในความเป็นจริงบางส่วนเป็นวิธีที่ดีในการเปลี่ยนบริบทการดูของคุณเช่นหากคุณมีเพจที่มีหลายรูปแบบที่โพสต์ไปยังการกระทำที่แตกต่างกันการแสดงผลบางส่วนสำหรับแต่ละส่วนจะเป็นความคิดที่ดี


เมื่อคุณได้สิ่งเหล่านี้ทั้งหมดแล้วคุณสามารถเริ่มทำสิ่งที่น่าสนใจได้ด้วยการExpression<>ขยายโปรแกรมและทำสิ่งอื่น ๆ ที่เป็นระเบียบ ฉันจะไม่เข้าใจอะไรเลย แต่หวังว่านี่จะช่วยให้คุณเข้าใจสิ่งที่เกิดขึ้นเบื้องหลังได้ดีขึ้นและเหตุใดสิ่งต่างๆจึงดำเนินไปอย่างที่เป็นอยู่


4
ตอบกลับน่ากลัว ฉันกำลังพยายามย่อยมันอยู่ :) ยังมีความผิด Cargo Culting! ชอบคำอธิบายนั้น.
David C

4
ขอบคุณสำหรับคำตอบโดยละเอียดนี้!
Kobi

14
ต้องการคะแนนโหวตมากกว่าหนึ่งรายการสำหรับสิ่งนี้ +3 (หนึ่งคำอธิบายแต่ละคำอธิบาย) และ +1 สำหรับผู้นับถือลัทธิขนส่งสินค้า คำตอบที่ยอดเยี่ยมแน่นอน!
Kyeotic

3
นี่คือเหตุผลที่ฉันชอบ SO: คำตอบสั้น ๆ + คำอธิบายเชิงลึก + ลิงก์ที่ยอดเยี่ยม (ลัทธิขนส่งสินค้า) ฉันอยากจะแสดงโพสต์เกี่ยวกับลัทธิขนส่งสินค้าให้กับทุกคนที่ไม่คิดว่าความรู้เกี่ยวกับการทำงานภายในของสิ่งของมีความสำคัญอย่างยิ่ง!
user1068352

18

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

มุมมองหลัก:

@model ViewModels.MyViewModels.Theme

@Html.LabelFor(Model.Theme.name)
@Html.EditorFor(Model.Theme.Categories)

มุมมองหมวดหมู่ (/MyController/EditorTemplates/Category.cshtml):

@model ViewModels.MyViewModels.Category

@Html.LabelFor(Model.Name)
@Html.EditorFor(Model.Products)

มุมมองผลิตภัณฑ์ (/MyController/EditorTemplates/Product.cshtml):

@model ViewModels.MyViewModels.Product

@Html.LabelFor(Model.Name)
@Html.EditorFor(Model.Orders)

และอื่น ๆ

วิธีนี้ Html.EditorFor helper จะสร้างชื่อขององค์ประกอบตามลำดับดังนั้นคุณจะไม่มีปัญหาอีกต่อไปในการดึงเอนทิตีธีมที่โพสต์โดยรวม


1
แม้ว่าคำตอบที่ได้รับการยอมรับจะเป็นคำตอบที่ดีมาก (ฉันโหวตให้ด้วย) คำตอบนี้เป็นตัวเลือกที่ดูแลรักษาได้มากกว่า
Aaron

4

คุณสามารถเพิ่มหมวดหมู่บางส่วนและบางส่วนของผลิตภัณฑ์ได้โดยแต่ละส่วนจะใช้ส่วนย่อยของโมเดลหลักเนื่องจากเป็นโมเดลของตัวเองเช่นประเภทโมเดลของหมวดหมู่อาจเป็น IEnumerable คุณจะส่งผ่านในโมเดลธีมไป บางส่วนของผลิตภัณฑ์อาจเป็นหมายเลขที่คุณสามารถส่งผ่าน Model.Products ไปยัง (จากภายในหมวดหมู่บางส่วน)

ฉันไม่แน่ใจว่าจะเป็นวิธีที่ถูกต้องหรือไม่ แต่สนใจที่จะรู้

แก้ไข

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


ที่เกิดขึ้นกับฉันเพียง แต่ไม่แน่ใจว่าจะจัดการกับมันอย่างไรเมื่อฉันอ่านมันเพื่ออัปเดต
David C

1
ใกล้แล้ว แต่เนื่องจากนี่เป็นแบบฟอร์มที่จะโพสต์เป็นหน่วยจึงใช้งานไม่ได้ เมื่ออยู่ภายในบางส่วนบริบทมุมมองได้เปลี่ยนไปและไม่มีนิพจน์ที่ซ้อนกันอย่างลึกซึ้งอีกต่อไป การโพสต์กลับไปที่Themeโมเดลจะไม่ได้รับความชุ่มชื้นอย่างเหมาะสม
J. Holmes

นั่นคือความกังวลของฉันเช่นกัน ฉันมักจะทำข้างต้นเป็นวิธีการอ่านอย่างเดียวในการแสดงผลิตภัณฑ์จากนั้นให้ลิงก์ในแต่ละผลิตภัณฑ์ไปยังวิธีการดำเนินการ / ผลิตภัณฑ์ / แก้ไข / 123 เพื่อแก้ไขแต่ละผลิตภัณฑ์ในรูปแบบของตัวเอง ฉันคิดว่าคุณสามารถยกเลิกการพยายามทำมากเกินไปบนหน้าเดียวใน MVC ได้
Adrian Thompson Phillips

@AdrianThompsonPhillips ใช่มันเป็นไปได้มากที่ฉันมี ฉันมาจากพื้นหลังของฟอร์มดังนั้นฉันจึงยังไม่คุ้นเคยกับความคิดที่จะต้องออกจากหน้าเพื่อทำการแก้ไข :(
David C

2

เมื่อคุณใช้ foreach loop ภายในมุมมองสำหรับโมเดลที่ถูกผูก ... โมเดลของคุณควรอยู่ในรูปแบบที่แสดงรายการ

กล่าวคือ

@model IEnumerable<ViewModels.MyViewModels>


        @{
            if (Model.Count() > 0)
            {            

                @Html.DisplayFor(modelItem => Model.Theme.FirstOrDefault().name)
                @foreach (var theme in Model.Theme)
                {
                   @Html.DisplayFor(modelItem => theme.name)
                   @foreach(var product in theme.Products)
                   {
                      @Html.DisplayFor(modelItem => product.name)
                      @foreach(var order in product.Orders)
                      {
                          @Html.TextBoxFor(modelItem => order.Quantity)
                         @Html.TextAreaFor(modelItem => order.Note)
                          @Html.EditorFor(modelItem => order.DateRequestedDeliveryFor)
                      }
                  }
                }
            }else{
                   <span>No Theam avaiable</span>
            }
        }

ฉันแปลกใจที่โค้ดด้านบนรวบรวมได้ @ Html.LabelFor ต้องการการดำเนินการ FUNC เป็นพารามิเตอร์คุณไม่ใช่
Jenna Leaf

ฉันไม่รู้ว่าโค้ดด้านบนคอมไพล์หรือไม่ แต่ซ้อน @foreach ใช้ได้กับฉัน MVC5.
อันโตนิโอ

0

เป็นที่ชัดเจนจากข้อผิดพลาด

HtmlHelpers ต่อท้ายด้วย "For" คาดว่านิพจน์แลมบ์ดาเป็นพารามิเตอร์

หากคุณกำลังส่งผ่านค่าโดยตรงให้ใช้ค่าปกติดีกว่า

เช่น

แทน TextboxFor (.... ) ให้ใช้ Textbox ()

ไวยากรณ์สำหรับ TextboxFor จะเป็นเช่น Html.TextBoxFor (m => m.Property)

ในสถานการณ์ของคุณคุณสามารถใช้พื้นฐานสำหรับลูปได้เนื่องจากจะทำให้คุณใช้ดัชนีได้

@for(int i=0;i<Model.Theme.Count;i++)
 {
   @Html.LabelFor(m=>m.Theme[i].name)
   @for(int j=0;j<Model.Theme[i].Products.Count;j++) )
     {
      @Html.LabelFor(m=>m.Theme[i].Products[j].name)
      @for(int k=0;k<Model.Theme[i].Products[j].Orders.Count;k++)
          {
           @Html.TextBoxFor(m=>Model.Theme[i].Products[j].Orders[k].Quantity)
           @Html.TextAreaFor(m=>Model.Theme[i].Products[j].Orders[k].Note)
           @Html.EditorFor(m=>Model.Theme[i].Products[j].Orders[k].DateRequestedDeliveryFor)
      }
   }
}

0

ความเป็นไปได้ที่ง่ายกว่ามากก็คือชื่อคุณสมบัติของคุณผิด (อาจเป็นชื่อที่คุณเพิ่งเปลี่ยนในคลาส) นี่คือสิ่งที่สำหรับฉันใน RazorPages .NET Core 3

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.