简体   繁体   English

动态编辑器用于使用模型中的模板

[英]Dynamic EditorFor using template from Model

The project is currently MVC3 but could be upgraded if required. 该项目当前为MVC3,但可以根据需要进行升级。

I'm trying to get a content editor for a simple cms improved. 我正在尝试为简单的cms改进内容编辑器。 At the moment we use 目前我们使用

@Html.EditorFor(model=>model.Content) //Content is a List<EditableContent>

EditableContent has a (brand new) property of string EditorView. EditableContent具有字符串EditorView的(全新)属性。 The idea is this will name suitable editors for particular items of content. 想法是,这将为特定的内容项命名合适的编辑器。

What I want to do is use my default EditableContent template if EditorView is null, otherwise use the EditorView as the named template. 我想做的是,如果EditorView为null,请使用默认的EditableContent模板,否则,请使用EditorView作为命名模板。 I'm aware of the overload for EditorFor that takes a template, but that's going to use the same template for each item of content, but that's not what I want. 我知道带有模板的EditorFor的重载,但是将对每个内容项使用相同的模板,但这不是我想要的。

I did try taking my default template and basically doing 我确实尝试过使用默认模板,基本上

//Shared/EditorTemplates/EditableContent.cshtml
@model Website.Areas.Admin.EditableContent

@if (!string.IsNullOrWhiteSpace(Model.EditorView))
{
<text>
    @Model.EditorView
    @Html.EditorForModel(Model.EditorView)
</text>
}
else
{
  //Original template
}

Weirdly in this case, the view is located (I have a slightly custom view engine which appears to locate the view correctly). 在这种情况下,奇怪的是,该视图已定位(我有一个稍微自定义的视图引擎,看起来似乎可以正确定位该视图)。 The name of the view (via @Model.EditorView ) is emitted to the page, but @Html.EditorForModel() doesn't produce anything. 视图的名称(通过@ Model.EditorView)被发送到页面,但是@ Html.EditorForModel()不会产生任何结果。

Any ideas how I can use a custom template per item using EditorFor or similar ? 有什么想法可以使用EditorFor或类似工具针对每个项目使用自定义模板吗?

Interface 接口

interface IEditableContent
{
    public virtual DatabaseContext.Content Content { get; set; }
}

Implementation 实作

class SomeTypeEditableContent : IEditableContent
{
    public SomeTypeEditableContent(DatabaseContext.Content c)
    {
        Content = c;
    }
}

Service (Repository or Controller action) 服务(存储库或控制器操作)

List<IEditableContent> lEditableContent = new List<IEditableContent>();
foreach(var c in db.Contents)
{
    switch (c.EditorView)
    {
    case "SomeType":
        lEditableContent.Add(new SomeTypeEditableContent(c));
        break;
    default:
        lEditableContent.Add(new DefaultEditableContent(c));
        break;
    }
}

View 视图

@Html.EditorFor(model=>model.ListContent) //List<IEditableContent>

Editable SomeType Template 可编辑的SomeType模板

@model SomeTypeEditableContent
//Display this as a editable string

Default Editable Content Template 默认可编辑内容模板

@model IEditableContent
//Use default display

I'm sorry I do not have the time to test it. 抱歉,我没有时间进行测试。 Let me know how it goes and i'll edit / delete this answer if it does not. 让我知道如何进行,如果没有,我将编辑/删除此答案。 I would have posted this as a comment but I needed anotation and formating. 我会将其发布为评论,但是我需要注释和格式。 But at least it gives you an idea of what I had in mind. 但是至少它使您对我的想法有所了解。

-Edit- -编辑-

The point of this exemple is to show you that MVC framework should be able to determine the proper template for a implementated interface even if simply providing the object typed as the interface. 这个例子的目的是向您展示MVC框架应该能够为已实现的接口确定正确的模板,即使只是提供类型为接口的对象也是如此。 It will use refelction (i believe?) to find the highest class definition then look for the template. 它将使用refelction(我相信吗?)找到最高的类定义,然后寻找模板。

-Edit 2 (based off comments)- -编辑2(基于注释)-

Changed the exemple to match new specifications 更改了示例以匹配新规范

It seems weird that you are trying to override the editor template from a view that is already overriding the template. 您试图从已经覆盖模板的视图中覆盖编辑器模板似乎很奇怪。 I'm not sure if that will work (it might, but I have never tried so I don't know). 我不确定这是否行得通(可能,但是我从未尝试过,所以我不知道)。 I've already added a couple comments to your question above. 我已经在上面的问题中添加了一些评论。

If it turns out that trying to specify templates from the EditorTemplates folder doesn't work, which would be understandable, I think you could achieve what you want by introducing a custom EditorForModel() override. 如果事实证明尝试从EditorTemplates文件夹中指定模板不起作用,这是可以理解的,我认为您可以通过引入自定义EditorForModel()覆盖来实现所需的功能。 You can use David Ebbo's Razor Generator VS extension to define a razor helper that will be usable across your entire project. 您可以使用David Ebbo的Razor Generator VS扩展来定义一个可在整个项目中使用的剃刀助手。

/// /Views/Helpers/AndiEditorForExtensions.cshtml
@helper AndiEditorFor(HtmlHelper html, Website.Areas.Admin.EditableContent model) {
    if (!string.IsNullOrWhiteSpace(Model.EditorView)) {
    <text>
        @Model.EditorView
        @Html.EditorForModel(Model.EditorView)
    </text>
    }
    else {
        // Call @Html.EditorFor(), which will use the default editor template (i.e., NOT your custom one defined in the database)
        @Html.EditorFor(model) 
    }
}

Then from your normal code that loads the EditableContent items from the db and displays them, call your custom extension: 然后,从从数据库加载并显示可编辑内容的常规代码中,调用自定义扩展名:

@Html.AndiEditorFor(model)

UPDATE: 更新:

A better option might be to skip the Razor Generator altogether. 更好的选择可能是完全跳过“剃刀生成器”。 Just define a custom HtmlHelper, mimicking the EditorExtensions methods . 只需定义一个自定义的HtmlHelper,模仿EditorExtensions方法即可 Add a similar if/else to handle Model.EditorView having a value or not. 添加类似的if / else来处理Model.EditorView是否具有值。

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

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