2010-11-12 10 views
7

Tworzę aplikację MVC, która aktualnie używa EditorFor do generowania wielu widoków. Cały widok to w zasadzie tylko EditorForModel i działa świetnie. Jednakże doszedłem do jednego małego problemu, na który nie mogę znaleźć rozwiązania, i ważne jest, aby działał tak, jak tego potrzebuję, i to jest podczas próby renderowania EditorFor interfejsu. Wiązania i wszystko to zostało załatwione, ale problem polega na tym, że EditorFor widzi, że jest to interfejs, a domyślnie szablon "Object". Potrzebuję go, aby spojrzeć na interfejs i sprawdzić, czy może znaleźć szablon o tej nazwie, a jeśli nie, potrzebuję go do przeglądania wszystkich obecnych interfejsów, aby sprawdzić, czy pasuje do żadnego z nich. Aby wyjaśnić to prościej spojrzeć na ten przykład:Przesłanianie domyślnego edytoraDo wyboru szablonu w ASP.NET MVC 3 RC

interfejsów:

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. 

Gdybym teraz utworzyć widok z Model = "IAppMusicProvider" i uruchom Html.EditorForModel(), muszę go znaleźć „~ Wyświetleń \ Shared \ EditorTemplates \ IAppProvider.cshtml "-template. Czy jest jakiś prosty sposób, w jaki mogę to osiągnąć?

Odpowiedz

1

Czy próbowałeś użyć atrybutu [TemplateHint]?

+0

tak, że działa, ale nie jest to sposób sobie z tym problemem (lub raczej użyłem właściwie atrybut '[DataType]'). Aplikacja, którą tworzę, będzie uruchamiać wtyczki i potrzebuję, aby działała tylko poprzez ustawienie interfejsu i nie zmuszanie wszystkich programistów wtyczek do użytkownika '[DataType (" IAppProvider ")]'. – Alxandr

+0

Spróbuj nazwać szablon tak samo jak interfejs? Jeśli pamiętam, to są tylko dwie opcje. – jfar

+0

To również nie działa, ponieważ szablon musi działać dla wszystkich 'IAppProvider's. Szukam sposobu na przesłonięcie tego domyślnego zachowania, więc jeśli dostarczę interfejs implementujący IAppProvider, użyje szablonu IAppProvider. To prawdopodobnie musi być zakodowane gdzieś w MVC (jakiś komponent, który musi zostać zmieniony, jak możesz to zrobić z ControllerFactory itp.), Ale nie wiem nawet, od czego zacząć. – Alxandr

1

Możesz spróbować zmienić ModelMetadata.TemplateHint w ModelMetadataProvider. Jednym ze sposobów na to jest ze wzoru dekorator:

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

I w logice rozruchu:

ModelMetadataProviders.Current = new AbstractTypeTemplateSupportingModelMetadataProvider(ModelMetadataProviders.Current); 
Powiązane problemy