【问题标题】:MVC3 Razor custom templates for primitive types and downcasting用于原始类型和向下转换的 MVC3 Razor 自定义模板
【发布时间】:2012-12-10 17:31:47
【问题描述】:

我有一个视图模型:

public class AttributeEditorViewModel
{
    public long AttributeId { get; set; }
    public string DisplayName { get; set; }
    public object Value { get; set; }
}

模型是使用模型构建器构建的,因此最终视图模型具有上述对象的列表:

public class AttributeListViewModel
{
    public List<AttributeEditorViewModel> Attributes { get; set; }
}

我的模型构建器编译了一个 AttributeEditorViewModel 对象列表并将适当的原始类型设置为 Value 属性。数据类型来自不同的属性定义。

现在 Razor 视图(比如说 edit.cshtml)看起来像:

@model AttributeListViewModel

@Html.EditorFor(m => m.Attributes)

以及编辑器模板 Views/Shared/EditorTemplates/AttributeEditorViewModel.cshtml:

@model AttributeEditorViewModel

<div>
    <label>@Model.DisplayName</label>
    @Html.EditorFor(m => m.Value)
    @Html.ValidationMessageFor(m => m.Value)
</div>

我的期望;如果我将 AttributeEditorViewModel 的 Value 属性设置为双精度,如下所示:

public ActionResult Edit()
{
    return View(new AttributeListViewModel 
    {
        Attributes = new List<AttributeEditorViewModel> 
        {
            new AttributeEditorViewModel { DisplayName = "Double example", Value = (double) 0 }
        }
    };
}

我希望会呈现一个文本框。相反,它什么也不渲染。我添加了另一个编辑器模板 Views/Shared/EditorTemplates/Double.cshtml:

@model double

@Html.TextBoxFor(m => m)

这解决了眼前的问题。所以现在我得到一个值为 0 的文本框。但是,即使在自定义编辑器模板中使用 EditorFor,也不会再次呈现任何内容。

使用对象作为基本类型是根本错误的吗?为什么使用EditorFor或EditorForModel时什么都不渲染?

任何见解都值得赞赏。

【问题讨论】:

  • 感谢您的所有回答。尽管所有答案都解释了很多,但最有意义的是有关使用的编译时绑定的提示。虽然有点反直觉。人们会期望运行时根据值的“实际”类型来决定使用哪个编辑器。无论如何,我已经在模型中添加了一个新属性 TypeName,它从字面上指定了要使用的编辑器。由我来为可能的类型名称创建所有编辑器模板。当我必须执行自定义模型绑定器以正确读取这些值时,我还发现它很有帮助。

标签: c# asp.net-mvc-3 templates razor casting


【解决方案1】:

这是因为 EditorFor 使用泛型参数上的编译时绑定来确定要渲染的模板。

而且由于默认情况下没有定义EditorFor&lt;object&gt;(),所以你什么也得不到。

我相信您可以根据需要为对象定义自己的编辑器模板,但更好的方法可能是使您的视图模型通用:

public class AttributeEditorViewModel<TValue>
{
    public long AttributeId { get; set; }
    public string DisplayName { get; set; }
    public TValue Value { get; set; }
}

但是,这可能并不理想,因为您不再拥有多态视图模型列表。

【讨论】:

    【解决方案2】:

    对象和编辑器的问题正是您希望它做什么,想象一下它包含一个包含 2,000,000 个 DataTables 的字典,每个 DataTables 包含 300 列和 20,000 行。它应该准确显示什么?在模型上使用 object 类型的属性本质上没有任何问题,只是不要指望 Razor 会根据你在对象中粘贴的内容神奇地知道它应该显示哪种编辑器。

    【讨论】:

      【解决方案3】:

      实际问题在于您的 Razor 视图代码。当你这样做时:

      @Html.EditorFor(m => m.Attributes)
      

      您告诉视图引擎为List&lt;AttributeEditorViewModel&gt; 寻找EditFor 模板不是为 AttributeEditorViewModel。所以它使用默认的ObjectTemplate

      [edit.chtml] 尝试类似:

      @model AttributeListViewModel
      
      @foreach (var att in Model.Attributes)
      {
        @Html.EditorFor(m => att)
      }
      

      我认为这个确切的答案行不通(我不在使用 VS atm 的机器上),但它可以让您了解您遇到的问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-05-17
        • 1970-01-01
        • 2013-07-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-18
        • 1970-01-01
        相关资源
        最近更新 更多