MVC 3 自定义模板和 EditorForModel 混淆

发布于 2024-11-10 21:49:02 字数 763 浏览 1 评论 0原文

据我了解,

给定一个视图模型

public class MyViewModel{
    public DateTime Date {get; set;}
    public MyClass Class {get; set;}
}

..一个视图Views\MyController\MyAction.cshtml

@model MyViewModel
@Html.DisplayForModel()

..一个部分视图Views\Shared\DisplayTemplates\DateTime.chstml

@model DateTime
Some Date

..另一个部分视图Views\Shared\DisplayTemplates\MyClass.cshtml

@model MyClass
My Class

..我应该得到

Date
Some Date
Class
My Class    

..但我只是得到

Date
Some Date

所以看来 DisplayForModel 找到了 DateTime 模板,但不是我的自定义模板,即使我遵循按属性类型命名它的约定。

我是不是错过了什么。我正在使用 MVC 3,并且相信 MVC 2 中已经提供了此功能

So as I understand it

Given a view model

public class MyViewModel{
    public DateTime Date {get; set;}
    public MyClass Class {get; set;}
}

.. a View Views\MyController\MyAction.cshtml

@model MyViewModel
@Html.DisplayForModel()

.. a partial View Views\Shared\DisplayTemplates\DateTime.chstml

@model DateTime
Some Date

.. another partial View Views\Shared\DisplayTemplates\MyClass.cshtml

@model MyClass
My Class

.. I should get

Date
Some Date
Class
My Class    

.. But I just get

Date
Some Date

So it seems DisplayForModel finds DateTime template but not my custom template, even though I am following the conventions of naming it by the type of the property.

Am I missing something. I am using MVC 3 and believe this feature was already available in MVC 2

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

捂风挽笑 2024-11-17 21:49:02

仔细阅读了 MVC 源代码后,发现这实际上是不可能的。

原因是 @Html.DisplayForModel() 尝试通过以下方式查找用于渲染的模板:

  • 首先查找模型类型的名称,即 MyViewModel.cshtmlMyViewModel.vbhtmlMyViewModel.ascx 等,位于 ~\Views~\Views[ControllerName] 位置, ~\Views\DisplayTemplates~\Views\Shared~\Views\Shared\DisplayTemplates
  • 如果没有找到,它将沿着模型的基本类型,依次尝试每种类型的名称,
  • 如果没有找到,最终将到达 Object,为此存在一个内置模板。

对象模板的设计使得它检索所有模型的属性,对于根据以下条件从元数据进行渲染:

metadata.ShowForDisplay
&& metadata.ModelType != typeof(EntityState)
&& !metadata.IsComplexType 
&& !templateInfo.Visited(metadata)

因此,任何复杂类型的属性都将始终被排除。我认为混乱来自 Brad Wilson 关于自定义对象模板的帖子,他在其中创建了自定义对象模板并解决了浅潜与深潜的问题。通过实现自定义深入对象模板,这将覆盖内置对象模板,并且可以呈现复杂类型。

Having perused the MVC source code, it turns out that this is, in fact, not possible.

The reason is that @Html.DisplayForModel() attempts to find a template to use for rendering, by:

  • first looking for the name of the model's type, i.e. MyViewModel.cshtml or MyViewModel.vbhtml or MyViewModel.ascx etc, in location ~\Views, ~\Views[ControllerName], ~\Views\DisplayTemplates, ~\Views\Shared, ~\Views\Shared\DisplayTemplates
  • if it is not found it will walk down the model's base types, attempting each type's name in turn
  • if none are found, it will eventually end up at Object, for which there exists a built-in template

The object template is designed such that it retrieves all the model's properties, for rendering, from metadata based on the following condition:

metadata.ShowForDisplay
&& metadata.ModelType != typeof(EntityState)
&& !metadata.IsComplexType 
&& !templateInfo.Visited(metadata)

Therefore any property that is a complex type will always be excluded. I think the confusion arises from Brad Wilson's post on custom object template, where he creates a custom object template and addresses the issue of Shallow Dive vs Deep Dive. By implementing a custom deep dive object template this will override the built-in object template and complex types can be rendered.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文