2010-11-12 57 views
7

我正在創建一個MVC-應用程序,它目前使用EditorFor來生成許多視圖。整個視圖基本上只是一個EditorForModel,而且效果很好。然而,我遇到了一個小問題,我似乎找不到解決方案,並且按照我需要的方式工作非常重要,也就是在嘗試渲染EditorFor一個接口時。綁定和類似的東西都已經被處理了,但問題是EditorFor看到它是一個接口,並且默認爲「Object」模板。我需要它來查看接口並查看它是否可以找到具有該名稱的模板,如果不能,我需要它查看當前存在的所有接口以查看它是否匹配其中的任何接口。爲了簡單地解釋一下這個例子:覆蓋ASP.NET MVC 3中的默認EditorFor模板選擇RC

接口:

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. 

如果我現在創建一個模型=「IAppMusicProvider」視圖,並運行Html.EditorForModel(),我需要它來找到「〜意見\共享\ EditorTemplates \ IAppProvider.cshtml「-template。有什麼簡單的方法可以實現這一目標嗎?

回答

1

您是否嘗試過使用[TemplateHint]屬性?

+0

呀,這樣的作品,但它不是解決問題的方式(或者更確切地說,我用實際上是[DataType]屬性)。我正在製作的應用程序將運行插件,我只需要通過設置接口來工作,而不必強制所有插件開發人員使用用戶[DataType(「IAppProvider」)]''。 – Alxandr 2010-11-12 02:56:47

+0

嘗試命名與界面相同的模板?如果我記得那是唯一的兩個選擇。 – jfar 2010-11-12 03:11:04

+0

這也不起作用,因爲模板需要適用於所有IAppProvider。我正在尋找一些方法來覆蓋這個默認行爲,所以如果我提供一個IAppProvider實現接口,它將使用IAppProvider模板。這可能需要在MVC的某處進行編碼(某些組件需要更改,就像您可以使用ControllerFactory等一樣),但我甚至不知道從哪裏開始。 – Alxandr 2010-11-12 03:16:02

1

您可以在ModelMetadataProvider中嘗試更改ModelMetadata.TemplateHint。這樣做的一個方法是使用Decorator模式:

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; 
    } 
} 

而且在你的啓動邏輯:

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