2013-07-03 15 views
9

Próbuję napisać ogólną (znaczącą przydatność w wielu miejscach) kontrolę, którą mogę ponownie wykorzystać w całej mojej firmie.Jak mogę utworzyć kontrolę "ogólną" w maszynie AspANet MVC Razor?

Mam problemy z rzeczywistymi generacjami C# w moim widoku i viewmodel.

Oto przykład tego, co próbuję zrobić:

Generic widok częściowy: (_Control.cshtml)

@model SimpleExample<dynamic> 

@Model.HtmlTemplate(Model.Data) 

ViewData: (SimpleExample.cs)

public class SimpleExample<T> 
{ 
    public T Data; 
    public Func<T, System.Web.WebPages.HelperResult> HtmlTemplate; 
} 

Przykład użycia: (FullView.cshtml)

@model Foo.MyViewData 

@Html.Partial("_Control", new SimpleExample<MyViewData> 
{ 
    Data = Model, 
    HtmlTemplate = @<div>@item.SomeProperty</div> 
}) 

Ważną częścią funkcjonalności, której szukam, jest to, że konsumenci uzyskują wpisany obiekt podczas pisania ich html w linii, aby mogli używać Intellisense (jak w FullView.cshtml).

Wszystko kompiluje grzywny i intellisense działa, ale jestem uzyskiwanie błąd się wykonawczego:

The model item passed into the dictionary is of type 
'AnytimeHealth.Web.ViewData.SimpleExample`1[Foo.MyViewData]', 
but this dictionary requires a model item of type 
'AnytimeHealth.Web.ViewData.SimpleExample`1[System.Object]'. 

Czytałem, że mogę być w stanie wykorzystać covarience na moim typu rodzajowego uzyskać to pracować, ale nie jestem pewien, jak to zrobić.

Czy możesz mi powiedzieć, jak mogę to usprawnić?

Odpowiedz

3

Zmiana określić w _Control.cshtml:

Zmiana ta @model SimpleExample<dynamic>

do @model dynamic i będzie działa, ale straci intellisense z SimpleExample i

intellisense z MyViewData będzie wciąż działa.

Myślę, że to dlatego, że dynamiczny typ będzie znany w czasie wykonywania, ale rodzaj leków generycznych

wymagają wczesnego czasu (być może jest kompilacji), w tym momencie, tylko object jest znana.

+0

To działa dla mnie, z wyjątkiem utraty intellisense w _Control ': (' – jjnguy

3

Można użyć ogólnego obiektu, a następnie, używając odbicia, wyrenderować właściwości tego obiektu (za pomocą pomocnika, aby wyświetlić listę właściwości). To samo podejście wykorzystywane przez Twitter Bootstrap dla MVC 4 (od strony Wich tego kodu została skopiowana, dla wygody): http://nuget.org/packages/twitter.bootstrap.mvc4

_Control.cshtml

@model Object 
@using (Html.BeginForm()) 
{ 
    @Html.ValidationSummary(true) 
    <fieldset> 
     <legend>@Model.GetLabel()</legend> 
     @foreach (var property in Model.VisibleProperties()) 
     { 
      using(Html.ControlGroupFor(property.Name)){ 
       @Html.Label(property.Name) 
       @Html.Editor(property.Name) 
       @Html.ValidationMessage(property.Name, null) 
      } 
     } 
     <button type="submit">Submit</button> 
    </fieldset> 
} 

Helper.cs

public static string GetLabel(this PropertyInfo propertyInfo) 
{ 
    var meta = ModelMetadataProviders.Current.GetMetadataForProperty(null, propertyInfo.DeclaringType, propertyInfo.Name); 
    return meta.GetDisplayName(); 
} 

public static PropertyInfo[] VisibleProperties(this IEnumerable Model) 
{ 
    var elementType = Model.GetType().GetElementType(); 
    if (elementType == null) 
    { 
     elementType = Model.GetType().GetGenericArguments()[0]; 
    } 
    return elementType.GetProperties().Where(info => info.Name != elementType.IdentifierPropertyName()).ToArray(); 
} 

public static PropertyInfo[] VisibleProperties(this Object model) 
{ 
    return model.GetType().GetProperties().Where(info => info.Name != model.IdentifierPropertyName()).ToArray(); 
} 
Powiązane problemy