Domanda

I have a model, which has a few regular properties like strings and integers, and it also have 2 ilist(of string) properties.

I made a DisplayTemplate for these that looks like this and is called ListOfString.vbhtml:

@ModelType List(Of String)
@If Model IsNot nothing And Model.Any Then
    @<ul> 
        @For i As Integer = 0 To Model.Count
            @<li>@Html.Raw(Model(i))</li> 
        Next
    </ul> 
end if

This is how the properties are decorated:

<UIHint("ListOfString")>
<Display(Name:="Options", ResourceType:=GetType(WebText))>
Public Property Options As List(Of String) = New List(Of String)

Then, in my view, I am calling @Html.DisplayForModel(). Expecting all my properties to be written out by the default Display templates, and my custom one for the lists for the properties that are lists.

All the properties that are not IList(of string) are rendered out fine (it's ugly, but that is a separate problem all together).

I tried having the Display Template in the Views/Shared/DisplayTemplates folder in the project base, and in the Area/Views/controllername/DisplayTemplates folder and neither work.

The lists DO have values in them, and the templates are not being rendered because I put plain "hello" in them and it did not show up. So it isn't a case of model binding going wrong.

Am I completely off my rocker in expecting this to work? I was under the impression that this was one of the great things about display templates and whatnot.

È stato utile?

Soluzione 2

I converted this C# Object Display Template linked by Denis to Visual Basic. Like the default object view template, it has a TemplateDepth check, but it's set to 5 instead of 1, and unlike the default, it displays views when metadata.IsComplexType is true.

@Code
    Dim shouldKnow As Func(Of ModelMetadata, Boolean) =
        Function(metadata) metadata.ShowForDisplay And Not ViewData.TemplateInfo.Visited(metadata)
End Code

@If ViewData.TemplateInfo.TemplateDepth > 5 Then
    If Model = Nothing Then
        @ViewData.ModelMetadata.NullDisplayText
    Else
        @ViewData.ModelMetadata.SimpleDisplayText
    End If
Else
    For Each prop In ViewData.ModelMetadata.Properties.Where(shouldKnow)
        If prop.HideSurroundingHtml Then
            @Html.Display(prop.PropertyName)
        Else
            @<div class="control-group">
                @Code
                    Dim label = Html.Label(prop.PropertyName)
                    If String.IsNullOrEmpty(label.ToHtmlString()) = False Then
                    @<div class="control-label">
                        @label
                    </div>
                    End If
                End Code
                <div class="controls">
                    @Html.Display(prop.PropertyName)
                </div>
            </div>
        End If
    Next
End If

Altri suggerimenti

It doesn't work because mvc has default display template for Object which renders only simple properties of model (like string, int and etc). You can override this template by adding partial view with name Object.xxx and model type Object to DisplayTemplates folder. You can look example of this template here https://github.com/BrandyFx/ProjectTemplate/blob/master/src/Web/Views/Shared/DisplayTemplates/Object.cshtml

Also you can find default implementation here https://github.com/githubmickey/ASP.NET-Web-Stack/blob/master/src/System.Web.Mvc/Html/DefaultDisplayTemplates.cs - internal static string ObjectTemplate

You can still display each property separately in your view (or a DisplayTemplate dedicated to your view model) :

@Html.DisplayFor(model => model.Options) 

This will use ListOfString.

Default DisplayTemplate for Object does not render complex type properties, so if you want to use @Html.DisplayForModel, you'll have to define a DisplayTemplate for your view model, including all your properties separately :

@ModelType MyCustomViewModel
@Html.DisplayFor(model => model.MyStringProp)<br />
@Html.DisplayFor(model => model.MyIntProp)<br />
@Html.DisplayFor(model => model.Options)

If you have a lot of properties, you can go with some more generic solution like in Denis' links.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top