繁体   English   中英

用于属性的ASP.NET MVC编辑器模板

[英]ASP.NET MVC editor template for property

通常我通过@ Html.RenderModel渲染我的表单,但这次我有一个复杂的渲染逻辑,我手动渲染它。 我决定为一个属性创建一个编辑器模板。 这是代码(从默认对象编辑器模板实现粘贴的副本):

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<% var modelMetadata = ViewData.ModelMetadata; %>
<% if (modelMetadata.HideSurroundingHtml) { %>
    <%= Html.Editor(modelMetadata.PropertyName) %>
<% } else { %>
    <% if (!String.IsNullOrEmpty(Html.Label(modelMetadata.PropertyName).ToHtmlString())) { %>
        <div class="editor-label"><%= Html.Label(modelMetadata.PropertyName) %></div>
    <% } %>
    <div class="editor-field">
        <%= Html.Editor(modelMetadata.PropertyName) %>
        <%= Html.ValidationMessage(modelMetadata.PropertyName) %>
    </div>
<% } %>

以下是我如何使用它:

@Html.EditorFor(x => x.SomeProperty, "Property") //"Property" is template above

但它不起作用:无论DisplayName如何都会呈现标签,并且根本不呈现编辑器(在Watches Html.Editor中(modelMetadata.PropertyName显示空字符串)。我做错了什么?

您正在从编辑器中调用编辑器。 正如@ RPM1984在这个答案中评论@ darin-dmitrov: 在给定的Views特定上下文中,您只能在给定类型的运行时使用1个模板

如果您将视图更改为渲染文本框而不是编辑器,它可以工作,我只是尝试:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<% var modelMetadata = ViewData.ModelMetadata; %>
<% if (modelMetadata.HideSurroundingHtml)
   { %>
   <%= Html.Editor(modelMetadata.PropertyName) %>
<% }
   else
   { %>
   <% if (!String.IsNullOrEmpty(modelMetadata.DisplayName))
       { %>
       <div class="editor-label"><%= Html.Label(modelMetadata.PropertyName) %></div>
    <% } %>
    <div class="editor-field"><%= Html.TextBox(modelMetadata.PropertyName) %> <%= Html.ValidationMessage(modelMetadata.PropertyName) %></div>
<% } %>

如果要渲染其他内容而不是文本框(即下拉列表),则需要在模板内部确定该属性并进行渲染。 或者,如果您有更多编辑器的共同点,我通常会将其提取到Shared文件夹中的部分视图中,并使用Html.Partial("ViewName")

并且, 无论DisplayName如何呈现标签 ,以防止在没有显示名称的情况下呈现标签,将if条件更改为!String.IsNullOrEmpty(modelMetadata.DisplayName) (我已经将它放在主代码块中)

编辑此编辑是指与object.ascx默认编辑器模板相关的问题。 这是object.ascx的代码,取自Brad Wilson的博客

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<% if (ViewData.TemplateInfo.TemplateDepth > 1) { %>
    <%= ViewData.ModelMetadata.SimpleDisplayText%>
<% }
   else { %>    
    <% foreach (var prop in ViewData.ModelMetadata.Properties.Where(pm => pm.ShowForEdit
                         && !ViewData.TemplateInfo.Visited(pm))) { %>
        <% if (prop.HideSurroundingHtml) { %>
            <%= Html.Editor(prop.PropertyName) %>
        <% }
           else { %>
            <% if (!String.IsNullOrEmpty(Html.Label(prop.PropertyName).ToHtmlString())) { %>
                <div class="editor-label"><%= Html.Label(prop.PropertyName) %></div>
            <% } %>
            <div class="editor-field">
                <%= Html.Editor(prop.PropertyName) %>
                <%= Html.ValidationMessage(prop.PropertyName, "*") %>
            </div>
        <% } %>
    <% } %>
<% } %>

这段代码确实从编辑器内部调用了Html.Editor,但是在一个循环中,它为复杂模型的属性创建了编辑器列表。 这些调用中的每一个都将调用相应的编辑器(即对于字符串,它将显示string.ascx等),并且只有当你有一些不是字符串的“unknown”属性并且没有特定的编辑器时(即byte [])它会为它调用object.ascx,但这不是调用当前属性的编辑器(你要做的是):

对象模板的主要职责是显示复杂对象的所有属性,以及每个属性的标签。 但是,它还负责显示模型的NullDisplayText的值(如果它为null),并且它还负责确保您只显示一个级别的属性(也称为对象的“浅层”)。 在下一篇博客文章中,我们将讨论自定义此模板的方法,包括执行“深度潜水”操作。


摘要

精简版:

相同属性的更多编辑器基本上是功能差异的解决方案(“是/否我想在这里收音机组和下拉列表”),并且对于视觉差异应该使用部分视图,因为您可以根据需要嵌套它们,因为你明确地通过名称调用它们所以没有限制,你有责任防止任何潜在的递归。

长版:

我一直在研究这个,因为我有同样的问题,我正在使用编辑器模板来渲染<li><td>元素(取决于配置/主题),并从内部调用另一个包含标签和输入的编辑器(相同)对于这两种情况,但如果属性是bool然后输入在标签之前),我再次调用第三个输入模板(以防止复制标签/输入和输入/标签方案的代码),但这不起作用。 虽然我没有在msdn或其他相关来源上找到解释,但我发现编辑器什么都没有给出的唯一情况就是当你想为属性渲染编辑器时,这是当前编辑器的上下文(所以它实际上就是我已经是引用:“在给定的Views特定上下文中,您只能在给定类型的运行时使用1个模板。”)。 在考虑了更多这方面之后,我相信他们现在正确实施这个限制,因为属性x只能使用一个编辑器来呈现。 您可以根据需要为属性x创建尽可能多的编辑器,但是使用多个模板无法渲染一个属性。 用于渲染属性x的任何模板都可以使用其他模板来渲染属性x的PARTS,但是您不能多次使用(相同或不同)x的编辑器(相同的逻辑适用于具有两个或更多属性x(相同类型)和名称)在同一型号上)。

此外,如果你可以将当前属性的另一个模板插入到当前模板中,那么可以为当前属性链接任意数量的模板,并且很容易导致递归,所以这样或那样会引导你进行stackoverflow :)

什么类型的“x.SomeProperty”? 我现在要假设它的类型叫做Property。

MyModel.cs

public class MyModel
{
    public Property SomeProperty { get; set; }
}

Property.cs

public class Property
{
    [Display(Name="Foo")]
    public int Value { get; set; }
}

查看/共享/ EditorTemplates / Property.cshtml

@model MvcApplication1.Models.Property

@Html.LabelFor(model => model.Value)
@Html.EditorFor(model => model.Value)
@Html.ValidationMessageFor(model => model.Value)

MyView.cshtml

@Html.EditorFor(model=>model.SomeProperty)

如果你没有为EditorFor helper提供templatename,它会找到editortemplate哪个名称与 SomeProperty的类型 匹配

更新:

要为字符串进行自定义editortemplate,您可以:

模型

public class MyModel
{
    public string SomeProperty { get; set; }
}

视图:

@Html.EditorFor(model => model.SomeProperty,"Property")

或者:

模型:

public class MyModel
{
    [DataType("Property")]
    public string SomeProperty { get; set; }
}

视图:

@Html.EditorFor(model => model.SomeProperty) 

查看/共享/ EditorTemplates / Property.cshtml:

@model string

@Html.Raw("I'm using property editortemplate:")
@Html.Label(ViewData.ModelMetadata.PropertyName)
@Html.Editor(ViewData.ModelMetadata.PropertyName)
@Html.ValidationMessage(ViewData.ModelMetadata.PropertyName)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM