2013-08-26 4 views
9

Używając tego pomocnika HTML w składni Razor:Szablony edytora ASP.NET MVC i Html.EditorFor (...) - jak rozróżnić nazwę typu?

@Html.EditorFor(model => model.Prop1) 

... konwencja jest do renderowania widoku pod Views/<CrtView|Shared>/EditorTemplates/Prop1TypeName.cshtml.

Jak dotąd tak dobrze. Zauważ, że jeśli (kwalifikowany) typ Prop1 to my.org.ns.TheType, plik TheType.cshtml zostanie wyrenderowany.

Ale jeśli mam model z .Prop1 i .Prop2 oraz:

Prop1.GetType().FullName == "my.org.ns1.TheType"; 
Prop2.GetType().FullName == "my.org.ns2.TheType"; //same type name but different namespace 

i nazywają to Razor:

@Html.EditorFor(model => model.Prop1) 
@Html.EditorFor(model => model.Prop2) 

... nie mogę zmusić go do wyświetlania inny wyświetleń różnych typów.

Czy istnieje sposób na ujednoznacznienie tego?

Może jest coś więcej, niż wiem o konwencji nazewnictwa dla pliku .cshtml?

Odpowiedz

2

Nie musisz koniecznie używać konwencji. Możesz mieć własne nazwy szablonów.

Jak to,

@Html.EditorFor(model => model.Prop1,"TheType_1") 
@Html.EditorFor(model => model.Prop2,"TheType_2") 

gdzie "TheType_1" & "TheType_2" są różne nazwy szablonów dla różnych typów. Jest to jeden z dostępnych six different overload methods.

9

Można użyć this overload, aby określić nazwę edytora, który ma być używany. W ten sposób nazwałbyś swoje edytoryTemplates First.cshtml i Second.cshtml, następnie w swoim Widoku, zrób to.

@Html.EditorFor(model => model.Prop1, "First") 
@Html.EditorFor(model => model.Prop2, "Second") 

Zalecam jednak unikanie ponownego użycia tego samego typu w tym samym projekcie, nawet jeśli mają one różne przestrzenie nazw. Spowoduje to zamieszanie dla kogoś czytającego kod, może nawet w dół drogi. Jest to większy problem niż ramy, które nie wiedzą, jaki szablon użyć.

+0

zgadzam się z zaleceniem nie używając tej samej nazwy typu, ale to nie jest możliwe w tym przypadku - jest to wygenerowany kod i nie mogę kontrolować, jakie typy nazw są generowane. –

5

Badając ASP.NET MVC source code (linia 164):

// TODO: Make better string names for generic types 
yield return fieldType.Name; 

To wydaje się, że zespół programistów ma świadomość, że to uproszczone podejście (fieldType.Name dla typu złożonego) może być potencjalność niejednoznaczne. Mam nadzieję, że znajdą elegancki sposób pozwalający nam wybrać szablony w bardziej elastyczny sposób.

W międzyczasie, można po prostu użyć atrybutu [UIHint], co następuje:

[UIHint("ns1.TheType")] 
public TheType Prop1 { get; set; } 

[UIHint("ns2.TheType")] 
public TheType Prop2 { get; set; } 

Update (jak na swoje komentarzu):

[UIHint] mogą być wykorzystywane wyłącznie na nieruchomości lub pole, dlatego nie możesz go użyć do dekoracji swojej klasy.

Można jednak stworzyć swój własny atrybut, który wywodzi się z UIHintAttribute:

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Class, AllowMultiple = true)] 
public class MyUIHintAttribute : UIHintAttribute 
{ 
    public MyUIHintAttribute(string templateName) : base(templateName) 
    { 
    } 
} 

Następnie ozdobić swoje zajęcia:

[MyUIHint("ns1.TheType")] 
public class TheType 
{ 
    .... 
} 

[MyUIHint("ns2.TheType")] 
public class TheType 
{ 
    .... 
} 
+0

+1, choć niezbyt przydatny w moim konkretnym scenariuszu (model jest listą pozycji heterogenicznych typów). Czy 'UIHint' (lub jest inny atrybut), który można zastosować na poziomie' * * zamiast dekorowania właściwości? –