简体   繁体   English

覆盖ASP.NET MVC 3 RC中的默认EditorFor模板选择

[英]Overriding the default EditorFor template-selecting in ASP.NET MVC 3 RC

I'm creating a MVC-application which currently uses EditorFor to gennerate a lot of views. 我正在创建一个MVC应用程序,它目前使用EditorFor来生成很多视图。 The whole view is basically just an EditorForModel, and it works great. 整个视图基本上只是一个EditorForModel,它运行得很好。 However, I've reached one small problem, which I can't seem to find a solution for, and it is important that it works the way I need it to, and that is when trying to render EditorFor an interface. 但是,我遇到了一个小问题,我似乎无法找到解决方案,并且重要的是它以我需要的方式工作,那就是在尝试渲染EditorFor一个接口时。 The bindings and everything like that's been taken care of, but the problem is that the EditorFor sees that it's an interface, and defaults to the "Object" template. 绑定和类似的一切都得到了处理,但问题是EditorFor看到它是一个接口,默认为“对象”模板。 I need it to look at the interface and see if it can find a template with that name, and if it can't, I need it to look trough all the interfaces present to see if it matches any of them. 我需要它来查看界面,看看它是否能找到具有该名称的模板,如果它不能,我需要它通过所有存在的接口来查看它是否与它们中的任何一个匹配。 To explain it more simply look at this example: 要更简单地解释一下这个例子:

interfaces: 接口:

public interface IAppProvider
{
    string Name { get; set; }
}

public interface IAppMusicProvider : IAppProvider
{
    int GetPlaylistCount();
} // Yeah, I know, this interface is not smart, but it's only for show.

If I now create a View with model = "IAppMusicProvider", and run Html.EditorForModel() , I need it to find the "~Views\\Shared\\EditorTemplates\\IAppProvider.cshtml"-template. 如果我现在使用model =“IAppMusicProvider”创建一个View,并运行Html.EditorForModel() ,我需要它来查找“〜Views \\ Shared \\ EditorTemplates \\ IAppProvider.cshtml”-template。 Is there any simple way I can achieve this? 有什么简单的方法可以达到这个目的吗?

You could try changing ModelMetadata.TemplateHint in the ModelMetadataProvider . 您可以尝试在ModelMetadata.TemplateHint中更改ModelMetadataProvider One way to do this is with the decorator pattern: 一种方法是使用装饰器模式:

public class AbstractTypeTemplateSupportingModelMetadataProvider : ModelMetadataProvider
{
    private readonly ModelMetadataProvider wrapped;

    public AbstractTypeTemplateSupportingModelMetadataProvider(ModelMetadataProvider wrapped)
    {
        this.wrapped = wrapped;
    }

    public override IEnumerable<ModelMetadata> GetMetadataForProperties(object container, Type containerType)
    {
        var result = this.wrapped.GetMetadataForProperties(container, containerType).ToList();
        result.ForEach(ChangeTemplateHint);

        return result;
    }

    public override ModelMetadata GetMetadataForProperty(Func<object> modelAccessor, Type containerType, string propertyName)
    {
        var result = this.wrapped.GetMetadataForProperty(modelAccessor, containerType, propertyName);
        ChangeTemplateHint(result);

        return result;
    }

    public override ModelMetadata GetMetadataForType(Func<object> modelAccessor, Type modelType)
    {
        var result = this.wrapped.GetMetadataForType(modelAccessor, modelType);
        ChangeTemplateHint(result);

        return result;
    }

    private void ChangeTemplateHint(ModelMetadata source)
    {
        if (source.Model is IAppProvider) //Or use source.ModelType if you want to support the model being null.
            source.TemplateHint = typeof(IAppProvider).Name;
    }
}

And in your start-up logic: 在你的启动逻辑中:

ModelMetadataProviders.Current = new AbstractTypeTemplateSupportingModelMetadataProvider(ModelMetadataProviders.Current);

您是否尝试使用[TemplateHint]属性?

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

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