SORU
17 Ocak 2012, Salı


MVC Razor view iç içe foreach'in modeli

Ortak bir senaryo hayal edin, bu genelinde geldim daha basit bir versiyonu. Ben aslında daha fazla mayın yerleştirme katmanları bir çift var....

Ama bu bir senaryodur

Tema Listesini içerir Kategori Listesini içerir Ürün Listesini içerir

Benim Kumanda tamamen dolu bir Tema, Bu tema için tüm Kategorileri bu kategori içindeki Ürünler ve onların emirleri ile sağlar.

Emir toplama özelliği düzenlenebilir gereken Miktar (diğerleri arasında) çağırdı.

@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)
      }
   }
}

Eğer öyleyse o zaman sadece üst Model nesne, "" foreach döngü içinde. bu Tema için bir başvuru almak gibi yerine lambda kullanırsam

Orada bile mümkün yapmaya çalışıyorum ne olduğunu ya da neyin mümkün olduğunu gözümde fazla büyütmüşüm ya da yanlış anlamış?

Yukarıdaki TextboxFor, EditorFor, vb bir hata alıyorum

CS0411: yöntem tür bağımsız değişkenleri 'Sistem.Web.Mvc.Html.İnputExtensions.TextBoxFor(Sistemi.Web.Mvc.HtmlHelper, Sistem.Seri.İfadeler.İfade>)' kullanımı olayla olamaz. Tür bağımsız değişkenleri belirten deneyin açıkça.

Teşekkürler.

CEVAP
17 Ocak 2012, Salı


Hızlı cevap foreach() döngüler for() bir döngü kullanmaktır. Gibi bir şey

@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)
      }
   }
}

Ama bu parlatıcılarnedenbu sorunu giderir.

Bu sorunu gidermek için önce en azından üstünkörü bir anlayışa sahip olan üç şey vardır. Ben 62 ** itiraf etmek bu çerçeve ile çalışmaya başladığımda uzun bir süre. Ve bana biraz zaman aldı neler olduğunu gerçekten.

O üç şey vardır:

  • Nasıl LabelFor ...For yardımcılar MVC mı?
  • İfade Ağaç nedir?
  • Nasıl Model Binder çalışır?

Bu kavramların üçü birlikte bir cevap almak için kullanılır.

Nasıl LabelFor ...For yardımcılar MVC mı?

Yani, LabelFor TextBoxFor ve diğerleri HtmlHelper<T> uzantıları kullandım ve muhtemelen onları çağırmak, onlara bir lambda ve pas olduğunu fark ettimsihirli bir şekildeoluşturur bazı html. Ama nasıl?

Fark ilk şey bu yardımcıların imzası. İçin en basit aşırı bakalım TextBoxFor

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

İlk olarak, bu türü kesin belirlenmiş HtmlHelper, türü için bir uzantı yöntemi <TModel>. Yani, basitçe perde arkasında ne devlet, jilet bu görünüm oluşturur bir sınıf oluşturur. Bu sınıfın içinde ** 23 (özelliği @Html... kullanabilirsiniz ediliyor Htmlgibi) bir örneğidir TModel * * * * türü @model ifadesi olarak tanımlanır. Bu yüzden, bu görüş bakarken senin durumunda, TModel her zaman 29 ** tip olacaktır.

Şimdi, bir sonraki argüman biraz zor. Böylece hadi bir çağırma bak

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

Küçük bir lambda var, Ve eğer bir imza tahmin etmek olsaydı, bir tip olduğunu düşünmüş olabilir gibi görünüyor bu bağımsız değişken yalnızca TModel modeli türü olduğu Func<TModel, TProperty> ve TPropertyolurdu bu özellik türü olarak sonuçlandı.

Ama bu tam olarak doğru değil, eğer bakarsanızgerçekdeğişken tipi Expression<Func<TModel, TProperty>>.

Normalde lambda oluşturduğunuzda, derleyici lambda alır ve MSIL derler aşağı, herhangi bir gibi yani sadece onlar Çünkü delegeler, yöntem grupları ve Lambda az ya da birbirinin yerine kullanabilirsiniz ediliyor (fonksiyon kod başvuruları.)

Derleyici türü Expression<> hemen MSIL aşağı lambda derleme değil bir görür, ancak bunun yerine bir oluşturur İfade Ağacı!

Expression Tree nedir?

Heck deyim ağacı ne demek. Peki, parkta bir yürüyüş ya ama onun kadar da karmaşık değil. Ms alıntı:

| İfade ağaçları her düğüm, bir ifade ağaç veri yapısı, kod, örneğin, bir yöntem çağrısı veya x < gibi bir ikili işlem; y temsil eder.

Basitçe ifade, bir ağaç topluluğu olarak bir işlev anlatımıdır "eylemler".

model=>model.SomeProperty ifade ağacın durumda diyor ki: öyle bir düğüm var ki "'Bazı özellikleri' a 'modeli".'

Bu ifade ağaç olabilirderlenmişama deyim ağacı olduğu sürece çağrılan bir işlev, sadece düğümler koleksiyonu.

Bunun için iyi nedir?

Onları bir kez Func<> Action<>, o kadar çok atom vardır. Gerçekten yapabileceğin tek şey onlara söyle aka Invoke() onları. bu işi yapmak gerekiyordu.

Diğer yandan Expression<Func<>>, eklenmiş olan eylemler, bir koleksiyon, visited compiled manipüle ve çağrılan temsil eder.

Bana bunları neden anlatıyorsun?

Expression<> ne olduğunu anlamadan, Html.TextBoxFor geri dönebiliriz. Bir textbox işler olduğunda, ihtiyaç duyduğu birkaç şey oluşturmak içinhakkındaözelliği veriyorsun. Doğrulama için mülkiyet attributes gibi şeyler, ve özellikle bu durumda ne olduğunu anlamaya ihtiyacı varadı<input> etiketi.

"İfade ağaç ve bina adı. "yürüyüş yapar model=>model.SomeProperty gibi bir ifade için ifade yürüyor yani istiyorsun ve <input name='SomeProperty'> inşa özellikleri toplama.

model=>model.Foo.Bar.Baz.FooBar gibi daha karmaşık bir örnek için, <input name="Foo.Bar.Baz.FooBar" value="[whatever FooBar is]" /> oluşturabilir

Mantıklı mı? Sadece Func<> yok bu iş olmaz amanasılçalışmalarını burada önemli değil.

(SERİ gibi diğer çerçeveler SQL deyim ağacı yürüyüş ve farklı bir dil bilgisi, bu durumda bir SQL sorgu) inşa ederek benzer şeyleri yapmayı unutmayın

Nasıl Model Binder çalışır?

Bunu bir kez anladığında, kısaca model binder hakkında konuşmamız gerek. Form gönderildi geldiğinde, sadece bir düz gibi Dictionary<string, string>, iç içe geçmiş bir görünüm modelimiz olmuş olabilir hiyerarşik yapısı kaybettik. Bu binder'in iş-değeri anahtar çifti ve bazı özellikleri ile bir nesne kaybı olmasın diye bu combo girişimi almaya model. Nasıl yapar bu? Tahmin edebileceğiniz gibi kullanarak "anahtar" ya da ilan var giriş adı.

Eğer form post gibi görünüyor

Foo.Bar.Baz.FooBar = Hello

Ve ilk etapta bir model SomeViewModel, yardımcı yaptıklarının ters geliyor adlı gönderiyorsunuz. Arar bir özellik olarak adlandırılan "". Foo Sonra bir özellik olarak adlandırılan arar "" "" o zaman arar ""... ve diğerleri... . Baz Foo kapalı Bar

Son olarak bu tür değeri ayrıştırmak için çalışır "" ve atamak "". Falanca Filanca

!! VAY be!

Ve viyola, modeliniz var. Örnek Model Binder sadece inşa istenen Eyleme teslim alır.


Çözüm Html.[Type]For() yardımcılar bir ifade lazım çünkü işe yaramıyor. Ve sadece onlara değer veriyoruz. Hiç bir fikrin yok içeriği nedir bu değer için, ve ne yapacağını bilmiyor.

Şimdi bazı insanlar parçaları işlemek için kullanmayı önerdi. Şimdi teorik olarak bu, ama muhtemelen beklediğiniz şekilde çalışır. Bir kısmi oluşturma, görünüm farklı bir bağlamda çünkü TModel, tipi değişiyor. Bu tarif anlamına gelir daha kısa bir ifade ile mülkiyet. Ayrıca yardımcı ifadeniz için Ad oluşturduğunda, sığ olacak demektir. Bu sadece üretecektir verilen bu ifadeye göre (tüm içerik).

Bu yüzden izin sadece, işlenen bir kısmi olduğunu "" (bizim örneğimizde önce). Baz Bu kısmi içinde sadece söyleyebiliriz:

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

Yerine

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

Böyle bir giriş etiketi oluşturacağı anlamına gelir:

<input name="FooBar" />

Eğer içe çok büyük bir ViewModel bekleniyor bir eylem bu form gönderme yapıyorsanız, o zaman bir özelliği nemlendirmek için çalışacağız FooBar TModel kapalı denir. En iyi değil, en kötüsü ise bambaşka bir şeydir. Eğer Baz yerine kök bir model kabul edeceği belirli bir eylem için gönderme olsaydı, o zaman bu büyük bir iş! Aslında elimizde iyi şekilde değiştirmek için Görünüm bağlam, örneğin eğer bir sayfada birden fazla form tüm yazı için farklı eylem, sonra bir işleme kısmi her biri için harika bir fikir.


Şimdi tüm bunları almak, Expression<>, gerçekten ilginç şeyler yapmak için programlama yoluyla onlara uzanan ve yaparak başlayabilirsiniz onlarla başka güzel şeyler. Bunun hiç girmeyeceğim. Ama umarım bu olur sen perde arkasında neler olduğunu ve şeyleri oldukları gibi davranıyorsunuz neden daha iyi bir anlayış verir.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Joseph Hayhoe

    Joseph Hayho

    20 Mayıs 2010
  • Randall P Studios

    Randall P St

    27 AĞUSTOS 2009
  • Samantha Crain

    Samantha Cra

    30 EKİM 2008