2012-08-30 128 views
12

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

<%@ 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 

但它没有工作:不管标签渲染显示名称的和编辑器根本没有呈现(在手表Html.Editor(modelMetadata.PropertyName显示空字符串)。我做错了什么?

回答

0

什么类型是“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) 

如果您没有为EditorFormer帮助程序提供templatename,它会找到名称匹配的编辑模板 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) 
+0

SomeProperty的类型是字符串,所以我期望文本框被呈现 – SiberianGuy

+0

查看更新的答案 –

+0

我不需要模板字符串,我需要一个通用模板的任何属性 – SiberianGuy

12

要调用的编辑器编辑器。作为@ RPM1984在@this中改写@ darin-dmitrov回答:在给定视图特定上下文中,您只能在运行时使用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> 
<% } %> 

如果你想渲染别的东西来代替文本框(即下拉列表),你需要决定在你的模板中为那个属性渲染它。或者,如果你有共同的更多的编辑东西,我通常提取到共享文件夹中的部分观点,并只使用Html.Partial("ViewName")

而且,关于标签,无论是渲染显示名称,防止标签的渲染是否有不显示名称,改变你如果条件!String.IsNullOrEmpty(modelMetadata.DisplayName)(我已经把它放在主代码块的方式)

编辑 这个编辑是指问题与object.ascx默认编辑模板。 这是object.ascx的代码,从Brad Wilson's blog采取:

<%@ 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等),并且仅当您有一些不是字符串的“未知”属性并且没有特定的编辑器时(即byte [])它会调用object.ascx它,但这是不呼吁为当前属性编辑器(你正在尝试做的):

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


摘要

短版:

更多的编辑器相同的属性基本上是功能上的差异的解决方案(“为是/否我想在这里无线电集团有下拉) “,对于视觉差异,应该使用部分视图,因为您可以尽可能多地嵌套它们,因为您明确地按名称调用它们,因此没有限制,您有责任防止任何潜在的递归。

龙版本:

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

此外,如果你可以插入当前财产另一模板到当前模板,使链接任意数量的用于当前属性模板,并可以很容易地引起递归,所以这种或那种方式会导致你计算器: )

+0

是的,我正在从编辑器调用编辑器,但与使用默认对象编辑器模板使用RenderModel时发生的情况相同。它适用于对象编辑器模板。那么我的代码与它有什么不同呢? – SiberianGuy

+1

您是指http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-3-default-templates.html中的默认模板吗?有一个区别,prop.PropertyName用于为复杂模型的属性调用编辑器,对于模型本身,使用<%= ViewData.ModelMetadata.SimpleDisplayText%>。请记住,对于所有属性,它们的默认编辑器将被调用,所以字符串属性等字符串,所以如果没有“特定”编辑器,它将调用具有显示文本的对象,因为该“未知”对象不能被编辑。 –

+0

你说得对,问题是我在这里有种递归。但我其实并没有看到ASP.NET MVC无法解决它的任何原因。 – SiberianGuy

相关问题