2011-05-31 16 views
6

मुझे लगता है कि एक आधार वस्तु संपादक टेम्पलेट लागू करने से पहले एक fieldset में मॉडल लपेटता एक संपादक टेम्पलेट का उपयोग कर एक दृश्य के मॉडल प्रदर्शित करने के लिए कोशिश कर रहा हूँ।क्या एकाधिक मॉडल टेम्पलेट्स के माध्यम से एक मॉडल पारित किया जा सकता है?

मेरा विचार:

@model Mvc3VanillaApplication.Models.ContactModel 

@using (Html.BeginForm()) 
{ 
    @Html.EditorForModel("Fieldset") 
} 

का उपयोग करता है एक fieldset टेम्पलेट (दृश्य/साझा/EditorTemplates/Fieldset.cshtml):

<fieldset> 
    <legend>@ViewData.ModelMetadata.DisplayName</legend> 
    @Html.EditorForModel() 
</fieldset> 

कौन सा बारी में एक बुनियादी टेम्पलेट का उपयोग करता है

: सभी वस्तुओं (दृश्य/साझा/EditorTemplates/Object.cshtml) के लिए
@foreach (var prop in ViewData.ModelMetadata.Properties.Where(x => 
    x.ShowForEdit && !x.IsComplexType && !ViewData.TemplateInfo.Visited(x))) 
{ 
    @Html.Label(prop.PropertyName, prop.DisplayName) 
    @Html.Editor(prop.PropertyName) 
} 

वैसे भी मेरा इरादा है। समस्या यह है कि जब पृष्ठ किसी फ़ील्ड और किंवदंती के साथ प्रस्तुत करता है, तो ऑब्जेक्ट टेम्पलेट लागू नहीं होता है इसलिए कोई इनपुट नियंत्रण प्रदर्शित नहीं होता है।

अगर मैं दृश्य बदलने फिर "fieldset" टेम्पलेट निर्दिष्ट नहीं करने के लिए अपने मॉडल के गुण वस्तु टेम्पलेट का उपयोग कर गाया जाता है, तो यह है कि मेरे वस्तु टेम्पलेट नहीं पाया जा सकता है नहीं है।

यह एक से अधिक टेम्पलेट के माध्यम से एक ही मॉडल पारित करने के लिए संभव है?

क्या इसके लायक है के लिए, दृश्य मॉडल इस तरह दिखता है:

namespace Mvc3VanillaApplication.Models 
{ 
    [System.ComponentModel.DisplayName("Contact Info")] 
    public class ContactModel 
    { 
     public string FirstName { get; set; } 
     public string LastName { get; set; } 
    } 
} 
+0

तो जटिल के साथ एक और टेम्पलेट कॉल कर सकते हैं। क्या आप अपना व्यू मॉडल कोड पोस्ट कर सकते हैं? तो हम आपके प्रश्न के बारे में और अधिक स्पष्ट हो सकते हैं। जैसा कि मुझे पता था, आप सभी संपादक के लिए उपयोग करने के लिए एक आम घटक बनाने की कोशिश करते हैं, है ना? – thangchung

+0

@ थांगचांग वैसे, मैं ऑब्जेक्ट एडिटर टेम्पलेट को ओवरराइड कर रहा हूं क्योंकि यह भारी है (divs में सबकुछ लपेट रहा है) और मैं इसे कुछ अन्य सम्मेलनों में लेने के लिए विस्तारित करना चाहता हूं। इसके अलावा, मैं फ़ील्ड टेम्पलेट का उपयोग कर रहा हूं इसलिए प्रत्येक मॉडल को फ़ील्ड में प्रदर्शित किया जाता है जो जावास्क्रिप्ट के माध्यम से विज़ार्ड में एक पृष्ठ बन जाता है। –

उत्तर

5

मैं कार्यान्वित तुम्हारे पास क्या है, और यह पुन: पेश करने में सक्षम था। मैं Object.cshtml में एक को तोड़ने बिंदु निर्धारित तो मैं निरीक्षण कर सकता है और मैं गार्ड बंद पकड़ा गया था एहसास है कि यह और भी जब fieldset टेम्पलेट का उपयोग किया जा रहा था ऑब्जेक्ट टेम्पलेट का पूरा उपयोग नहीं किया गया था। फिर मैंने फ़ील्ड टेम्पलेट के माध्यम से कदम रखा और देखा कि यह टेम्पलेट को ठीक से कॉल कर रहा था, इसलिए कोड में कुछ होना चाहिए जो ऑब्जेक्ट टेम्पलेट को प्रदर्शित करने से रोकता है।

मैंने MVC3 source code खोला, EditorForModel के लिए खोज की और सही कार्य पाया।

public static MvcHtmlString EditorForModel(this HtmlHelper html) { 
    return MvcHtmlString.Create(TemplateHelpers.TemplateHelper(html, html.ViewData.ModelMetadata, String.Empty, null /* templateName */, DataBoundControlMode.Edit, null /* additionalViewData */)); 
} 

जाहिर है इस यह नहीं था, इसलिए मैं TemplateHelpers.TemplateHelper पर F12 दबाया, और एक बार फिर से वहां मैं एक लाइन कॉल जो आप समारोह के मांस के लिए लाता है पर F12 दबाया।

// Normally this shouldn't happen, unless someone writes their own custom Object templates which 
// don't check to make sure that the object hasn't already been displayed 
object visitedObjectsKey = metadata.Model ?? metadata.RealModelType; 
if (html.ViewDataContainer.ViewData.TemplateInfo.VisitedObjects.Contains(visitedObjectsKey)) { // DDB #224750 
    return String.Empty; 
} 

उन टिप्पणियों कोड में वास्तव में कर रहे हैं, और यहाँ हम आपके सवाल का जवाब है: एक मॉडल कई संपादक टेम्पलेट्स के माध्यम से पारित किया जा सकता है यहाँ मैं कोड की इस छोटी सी बिट TemplateHelpers.cs की लाइन 214 से शुरू होने पाया ?, जवाब कोई * है।

कहा जा रहा है कि यह ऐसी सुविधा के लिए एक बहुत ही उचित उपयोग मामले की तरह लगता है, इसलिए एक विकल्प ढूंढना संभवतः प्रयास के लायक है। मुझे संदेह था कि एक टेम्पलेटेड रेजर प्रतिनिधि इस रैपिंग कार्यक्षमता को हल करेगा, इसलिए मैंने इसे आजमाया।

@{ 
    Func<dynamic, object> fieldset = @<fieldset><legend>@ViewData.ModelMetadata.DisplayName</legend>@Html.EditorForModel()</fieldset>; 
} 

@using (Html.BeginForm()) 
{ 
    //@Html.EditorForModel("Fieldset") 
    //@Html.EditorForModel() 
    @fieldset(Model) 
} 

और व्हायोला! इसने काम कर दिया! इसे एक विस्तार (और अधिक पुन: प्रयोज्य) विधि के रूप में लागू करने के लिए मैं इसे आपके पास छोड़ दूंगा।यहां templated razor delegates के बारे में एक लघु ब्लॉग पोस्ट है।


* तकनीकी तौर पर आप इस समारोह को फिर से लिखने सकता है और MVC3 के अपने स्वयं के संस्करण संकलन, लेकिन यह शायद अधिक परेशानी से इसके लायक है। हमने careers प्रोजेक्ट पर ऐसा करने का प्रयास किया जब हमें पता चला कि Html.ActionLink फ़ंक्शन काफी धीमा है जब आपके पास कुछ सौ मार्ग परिभाषित किए गए हैं। बाकी पुस्तकालयों के साथ एक हस्ताक्षर मुद्दा है जिसे हमने तय किया है, अब हमारे काम के लायक नहीं है और एमवीसी की भावी रिलीज के लिए बनाए रखा है।

+1

पूरी तरह से जवाब के लिए धन्यवाद; एक विस्तार विधि जाने के रास्ते की तरह लगता है। मैंने स्रोत में देखा और देखा (TemplateInfo.cs: 33) कि अनंत रिकर्सन को रोकने के लिए देखा गया ऑब्जेक्ट्स हैशसेट जोड़ा गया था। ऐसा लगता है कि यह बेहतर हो सकता है अगर एमवीसी टीम ने मॉडल के बजाय सेट में मॉडल और टेम्पलेट के संयोजन का उपयोग किया हो। इस तरह यह अभी भी रिकर्सन को रोक देगा लेकिन कई टेम्पलेट्स को लागू करने की अनुमति देगा। हालांकि मैं एमवीसी के अपने संस्करण को रोल करने से दूर रहूंगा। –

+0

@EricBock: मॉडल को 'फ़ील्डसेट व्यू मॉडेल' में मॉडल को लपेटने का एक और विकल्प हो सकता है जिसमें केवल 1 प्रॉपर्टी, ऑब्जेक्ट हो। हालांकि यह थोड़ा बोझिल लगता है। –

0

पहले cshtml टेम्पलेट में हम ViewData.TemplateInfo (और स्पष्ट VisitedObjects सूची) को पुन: कर सकते हैं

var templateInfo = ViewData.TemplateInfo; 
ViewData.TemplateInfo = new TemplateInfo 
{ 
    HtmlFieldPrefix = templateInfo.HtmlFieldPrefix, 
    FormattedModelValue = templateInfo.FormattedModelValue 
}; 

अब हम एक ही मॉडल

@Html.DisplayForModel("SecondTemplate") 
संबंधित मुद्दे