2013-09-30 1 views
5

Ich habe ein abstraktes ModellMVC Attribute auf abstrakte Eigenschaften

public abstract class Treasure { 
    public abstract int Value { get; } 
    public abstract string Label { get; } 
} 

und eine Implementierung

public class Coins : Treasure { 
    [DisplayName("Coin Value")] 
    public override int Value { 
     get { ... } 
    } 

    [DisplayName("Coins")] 
    public override string Label { 
     get { ... } 
    } 

Meine Münzen Objekt nicht zeigen „Münzen“ als Etikett meiner Meinung nach, wenn ich Html.LabelFor verwenden auf Es zeigt "Label". Wenn ich das DisplayName-Attribut in Treasure verschiebe, funktioniert es ... aber ich muss in der Lage sein, die Bezeichnung für verschiedene Implementierungen der Treasure-Klasse zu ändern. Ist das möglich?

+0

Und was ist das Modell in der Ansicht ... Schatz oder Münzen? – CrazyDart

+0

Haben Sie versucht, einen Standardwert für das Treasure-Objekt und das Coins-Objekt zu implementieren? nur ein Gedanke. –

+0

Nur um klar zu sein, wäre es gut, den Ausschnitt von Razor Markup zu sehen, der "LabelFor" enthält. –

Antwort

4

Ich konnte dies gut funktionieren, wenn das Modell in der Ansicht Coins ist. Wenn das Modell jedoch Schatz ist, schlägt es fehl. Warum? Denn wenn der HTML-Helper den HTML-Code rendert, sieht er nur den Modelltyp, der in der Ansicht angegeben ist, und nicht den Objekttyp des tatsächlichen Objekts. Wenn es zum Erhalten des Attributs kommt, erhält es nur das Attribut für Schatz und nicht Münzen. Ich denke, du müsstest dafür deinen eigenen HTML-Helfer schreiben.

internal static MvcHtmlString LabelFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, string labelText, IDictionary<string, object> htmlAttributes, ModelMetadataProvider metadataProvider) 
{ 
    return LabelExtensions.LabelHelper((HtmlHelper) html, ModelMetadata.FromLambdaExpression<TModel, TValue>(expression, html.ViewData, metadataProvider), ExpressionHelper.GetExpressionText((LambdaExpression) expression), labelText, htmlAttributes); 
} 

Unter den Abdeckungen, MVC verwendet ModelMetadata.FromLambdaExpression<TModel, TValue> die „Displayname“ zu finden, und wenn es nicht eine von der Art in weitergegeben finden ... es die PropertyName zurückgibt.

internal static MvcHtmlString LabelHelper(HtmlHelper html, ModelMetadata metadata, string htmlFieldName, string labelText = null, IDictionary<string, object> htmlAttributes = null) 
{ 
    string str = labelText; 
    if (str == null) 
    { 
    string displayName = metadata.DisplayName; 
    if (displayName == null) 
    { 
     string propertyName = metadata.PropertyName; 
     if (propertyName == null) 
     str = Enumerable.Last<string>((IEnumerable<string>) htmlFieldName.Split(new char[1] 
     { 
      '.' 
     })); 
     else 
     str = propertyName; 
    } 
    else 
     str = displayName; 
    } 
    string innerText = str; 
    if (string.IsNullOrEmpty(innerText)) 
    return MvcHtmlString.Empty; 
    TagBuilder tagBuilder1 = new TagBuilder("label"); 
    tagBuilder1.Attributes.Add("for", TagBuilder.CreateSanitizedId(html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(htmlFieldName))); 
    tagBuilder1.SetInnerText(innerText); 
    TagBuilder tagBuilder2 = tagBuilder1; 
    bool flag = true; 
    IDictionary<string, object> attributes = htmlAttributes; 
    int num = flag ? 1 : 0; 
    tagBuilder2.MergeAttributes<string, object>(attributes, num != 0); 
    return TagBuilderExtensions.ToMvcHtmlString(tagBuilder1, TagRenderMode.Normal); 
} 
+0

Gute Erklärung mit Code. In der Tat sieht es bei '@ Model' Deklaration nicht den eigentlichen Typ. –

Verwandte Themen