سؤال

لنفترض أن لدي ViewModel

public class AnotherViewModel
{
   public string Name { get; set; }
}
public class MyViewModel
{
   public string Name { get; set; }
   public AnotherViewModel Child { get; set; }
   public AnotherViewModel Child2 { get; set; }
}

في الرأي يمكنني تقديم جزئي مع

<% Html.RenderPartial("AnotherViewModelControl", Model.Child) %>

في الجزئي سأفعل

<%= Html.TextBox("Name", Model.Name) %>
or
<%= Html.TextBoxFor(x => x.Name) %>

ومع ذلك، فإن المشكلة هي أن كلا من سيعقد الاسم = "الاسم" بينما أحتاج إلى الحصول على اسم = "child.name" من أجل موثق النموذج للعمل بشكل صحيح. أو اسم = "child2.name" عند تقديم الخاصية الثانية باستخدام نفس الرأي الجزئي.

كيف يمكنني جعل عرضي الجزئي يتعرف تلقائيا على البادئة المطلوبة؟ يمكنني تمريرها كمعلمة ولكن هذا غير مريح للغاية. هذا أسوأ من الأسوأ عندما أرغب في تقديمه في تقديمه بشكل متكرر. هل هناك طريقة لتقديم وجهات نظر جزئية بادئة، أو حتى أفضل، مع استكشاف التلقائي من تعبير Lambda المكالمات بحيث

<% Html.RenderPartial("AnotherViewModelControl", Model.Child) %>

سوف تضيف تلقائيا الصحيح "الطفل". بادئة إلى سلاسل الاسم / الهوية الناتجة؟

يمكنني قبول أي حل، بما في ذلك محركات ومكتبات عرض الحزب 3-RD - فأنا فعلا استخدام محرك Spark View ("حل" المشكلة باستخدام وحدات الماكرو) و MVCContrib، ولكن لم تجد حلا هناك. XForms، Inputbuilder، MVC V2 - أي أداة / نظرة ثاقبة توفر هذه الوظيفة رائعة.

حاليا أفكر في الترميز هذا بنفسي، لكن يبدو أن مضيعة للوقت، لا أستطيع أن أصدق أن هذه الأشياء تافهة غير موجودة بالفعل.

قد توجد الكثير من الحلول اليدوية، وكلها موضع ترحيب. على سبيل المثال، يمكنني إجبار الجزئي على أن تكون مقرها إيقاف تشغيل iPartialViewModelu003CT> {بادئة السلسلة العامة؛ طراز t؛ }. لكنني أفضل تفضل بعض الحل الحالي / المعتمدة.

تحديث: هناك سؤال مماثل مع عدم وجود إجابة هنا.

هل كانت مفيدة؟

المحلول

يمكنك تمديد فئة مساعد HTML عن طريق هذا:

using System.Web.Mvc.Html


 public static MvcHtmlString PartialFor<TModel, TProperty>(this HtmlHelper<TModel> helper, System.Linq.Expressions.Expression<Func<TModel, TProperty>> expression, string partialViewName)
    {
        string name = ExpressionHelper.GetExpressionText(expression);
        object model = ModelMetadata.FromLambdaExpression(expression, helper.ViewData).Model;
        var viewData = new ViewDataDictionary(helper.ViewData)
        {
            TemplateInfo = new System.Web.Mvc.TemplateInfo
            {
                HtmlFieldPrefix = name
            }
        };

        return helper.Partial(partialViewName, model, viewData);

    }

واستخدامها ببساطة في وجهات نظركم مثل هذا:

<%= Html.PartialFor(model => model.Child, "_AnotherViewModelControl") %>

وسترى كل شيء على ما يرام!

نصائح أخرى

حتى الآن، كنت أبحث عن نفس الشيء الذي وجدته هذا المنشور الأخير:

http://davybrion.com/blog/21/01/prefixing-input-elements-partial-views-with-asp-net-mvc/

<% Html.RenderPartial("AnotherViewModelControl", Model.Child, new ViewDataDictionary
{
    TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = "Child1" }
})
%>

إجابتي بناء على إجابة محمود مورافج بما في ذلك تعليق إيفان زلاتيف.

    public static MvcHtmlString PartialFor<TModel, TProperty>(this HtmlHelper<TModel> helper, System.Linq.Expressions.Expression<Func<TModel, TProperty>> expression, string partialViewName)
    {
            string name = ExpressionHelper.GetExpressionText(expression);
            object model = ModelMetadata.FromLambdaExpression(expression, helper.ViewData).Model;
            StringBuilder htmlFieldPrefix = new StringBuilder();
            if (helper.ViewData.TemplateInfo.HtmlFieldPrefix != "")
            {
                htmlFieldPrefix.Append(helper.ViewData.TemplateInfo.HtmlFieldPrefix);
                htmlFieldPrefix.Append(name == "" ? "" : "." + name);
            }
            else
                htmlFieldPrefix.Append(name);

            var viewData = new ViewDataDictionary(helper.ViewData)
            {
                TemplateInfo = new System.Web.Mvc.TemplateInfo
                {
                    HtmlFieldPrefix = htmlFieldPrefix.ToString()
                }
            };

        return helper.Partial(partialViewName, model, viewData);
    }

تحرير: إجابة Mohamoud غير صحيحة للتقديم الجزئي المتداخلة. تحتاج إلى إلحاق البادئة الجديدة بالبادئة القديمة، فقط إذا كان ذلك ضروريا. لم يكن هذا واضحا في أحدث الإجابات (:

باستخدام MVC2 يمكنك تحقيق ذلك.

فيما يلي طريقة العرض المكتوبة بشدة:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MvcLearner.Models.Person>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Create
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <h2>Create</h2>

    <% using (Html.BeginForm()) { %>
        <%= Html.LabelFor(person => person.Name) %><br />
        <%= Html.EditorFor(person => person.Name) %><br />
        <%= Html.LabelFor(person => person.Age) %><br />
        <%= Html.EditorFor(person => person.Age) %><br />
        <% foreach (String FavoriteFoods in Model.FavoriteFoods) { %>
            <%= Html.LabelFor(food => FavoriteFoods) %><br />
            <%= Html.EditorFor(food => FavoriteFoods)%><br />
        <% } %>
        <%= Html.EditorFor(person => person.Birthday, "TwoPart") %>
        <input type="submit" value="Submit" />
    <% } %>

</asp:Content>

فيما يلي طريقة العرض المكتوبة بشدة لفئة الطفل (والتي يجب تخزينها في مجلد فرعي لدليل العرض المسمى EditectorTemplates):

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MvcLearner.Models.TwoPart>" %>

<%= Html.LabelFor(birthday => birthday.Day) %><br />
<%= Html.EditorFor(birthday => birthday.Day) %><br />

<%= Html.LabelFor(birthday => birthday.Month) %><br />
<%= Html.EditorFor(birthday => birthday.Month) %><br />

هنا هو وحدة تحكم:

public class PersonController : Controller
{
    //
    // GET: /Person/
    [AcceptVerbs(HttpVerbs.Get)]
    public ActionResult Index()
    {
        return View();
    }

    [AcceptVerbs(HttpVerbs.Get)]
    public ActionResult Create()
    {
        Person person = new Person();
        person.FavoriteFoods.Add("Sushi");
        return View(person);
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Create(Person person)
    {
        return View(person);
    }
}

فيما يلي الطبقات المخصصة:

public class Person
{
    public String Name { get; set; }
    public Int32 Age { get; set; }
    public List<String> FavoriteFoods { get; set; }
    public TwoPart Birthday { get; set; }

    public Person()
    {
        this.FavoriteFoods = new List<String>();
        this.Birthday = new TwoPart();
    }
}

public class TwoPart
{
    public Int32 Day { get; set; }
    public Int32 Month { get; set; }
}

ومصدر الإخراج:

<form action="/Person/Create" method="post"><label for="Name">Name</label><br /> 
    <input class="text-box single-line" id="Name" name="Name" type="text" value="" /><br /> 
    <label for="Age">Age</label><br /> 
    <input class="text-box single-line" id="Age" name="Age" type="text" value="0" /><br /> 
    <label for="FavoriteFoods">FavoriteFoods</label><br /> 
    <input class="text-box single-line" id="FavoriteFoods" name="FavoriteFoods" type="text" value="Sushi" /><br /> 
    <label for="Birthday_Day">Day</label><br /> 
    <input class="text-box single-line" id="Birthday_Day" name="Birthday.Day" type="text" value="0" /><br /> 

    <label for="Birthday_Month">Month</label><br /> 
    <input class="text-box single-line" id="Birthday_Month" name="Birthday.Month" type="text" value="0" /><br /> 
    <input type="submit" value="Submit" /> 
</form>

الآن هذا كامل. قم بتعيين نقطة توقف في إجراء إنشاء "إنشاء وحدة تحكم" للتحقق. لا تستخدم هذا مع قوائم ومع ذلك لأنه لن يعمل. انظر سؤالي على استخدام EdifetRemplates مع ienumerable لمزيد من ذلك.

هذا سؤال قديم، ولكن لأي شخص يصل هنا يبحث عن حل، والنظر في استخدام EditorFor, ، كما اقترح في التعليق في https://stackoverflow.com/a/29809907/456456.. وبعد للانتقال من وجهة نظر جزئية إلى قالب محرر، اتبع هذه الخطوات.

  1. تحقق من أن عرضك الجزئي مرتبط Complexxtype..

  2. حرك وجهة نظرك الجزئية إلى مجلد فرعي Editortemplates. من مجلد عرض الحالي، أو إلى المجلد مشترك. وبعد الآن، إنه قالب محرر.

  3. يتغيرون @Html.Partial("_PartialViewName", Model.ComplexType) ل @Html.EditorFor(m => m.ComplexType, "_EditorTemplateName"). وبعد قالب المحرر هو اختياري إذا كان القالب الوحيد للنوع المعقد.

سيتم تسمية عناصر إدخال HTML تلقائيا ComplexType.Fieldname.

Partailfor. ل ASP.NET Core 2 في حالة يحتاج شخص ما.

    public static ModelExplorer GetModelExplorer<TModel, TResult>(this IHtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TResult>> expression)
    {
        if (expression == null)
            throw new ArgumentNullException(nameof(expression));
        return ExpressionMetadataProvider.FromLambdaExpression(expression, htmlHelper.ViewData, htmlHelper.MetadataProvider);
    }

    public static IHtmlContent PartialFor<TModel, TResult>(this IHtmlHelper<TModel> helper, Expression<Func<TModel, TResult>> expression, string partialViewName, string prefix = "")
    {
        var modelExplorer = helper.GetModelExplorer(expression);
        var viewData = new ViewDataDictionary(helper.ViewData);
        viewData.TemplateInfo.HtmlFieldPrefix += prefix;
        return helper.Partial(partialViewName, modelExplorer.Model, viewData);
    }

صادفت هذه المشكلة أيضا وبعد الكثير من الألم، وجدت أنه من الأسهل إعادة تصميم واجهاتي بحيث لم أكن بحاجة إلى نشر كائنات نموذجية متداخلة. أجبرني هذا على تغيير سير عمل واجهة بلدي: من المؤكد أنني أتطلب الآن من المستخدمين الآن القيام به في خطوتين عما حلمت به في واحدة، لكن قابلية الاستخدام وإمكانية التمويل الرمز النهج الجديد له قيمة أكبر بالنسبة لي الآن.

آمل أن يساعد هذا بعض.

يمكنك إضافة مساعد ل RenderPartial التي تأخذ البادئة وملثفها في ViewData.

    public static void RenderPartial(this HtmlHelper helper,string partialViewName, object model, string prefix)
    {
        helper.ViewData["__prefix"] = prefix;
        helper.RenderPartial(partialViewName, model);
    }

ثم مساعد آخر يلزف قيمة ViewData

    public static void GetName(this HtmlHelper helper, string name)
    {
        return string.Concat(helper.ViewData["__prefix"], name);
    }

وهكذا في المنظر ...

<% Html.RenderPartial("AnotherViewModelControl", Model.Child, "Child.") %>

في الجزئي ...

<%= Html.TextBox(Html.GetName("Name"), Model.Name) %>

مثلك، أقوم بإضافة خاصية البادئة (سلسلة) إلى رأيي التي ألغيتها قبل أسماء المدخلات الملزمة بالنموذج. (Yagni منع أدناه)

قد يكون الحل الأكثر أناقة نموذجا رائعا نموذجا يحتوي على هذه الخاصية وبعض HTMLHELPERS الذي تحقق مما إذا كان نموذج العرض مستمد من هذه القاعدة وإذا كان الأمر كذلك إلحاق بادئة اسم الإدخال.

امل ان يساعد،

دان

ماذا عن قبل استدعاء renderpartial أنت تفعل

<% ViewData["Prefix"] = "Child."; %>
<% Html.RenderPartial("AnotherViewModelControl", Model.Child) %>

ثم في جزئيتك لديك

<%= Html.TextBox(ViewData["Prefix"] + "Name", Model.Name) %>
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top