2013-07-03 42 views
9

Tôi đang cố gắng viết một điều khiển chung (có nghĩa là hữu ích ở nhiều nơi) mà tôi có thể sử dụng lại trong toàn bộ công ty của mình.Làm cách nào để tạo điều khiển 'chung' trong Asp.Net MVC Razor?

Tôi gặp sự cố với các đại lượng C# thực tế trong chế độ xem và chế độ xem của mình.

Dưới đây là một ví dụ về những gì tôi đang cố gắng để làm:

Generic xem phần: (_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; 
} 

sử dụng Ví dụ: (FullView.cshtml)

@model Foo.MyViewData 

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

Phần quan trọng của chức năng tôi đang tìm kiếm là người tiêu dùng nhận được đối tượng đã nhập khi viết nội tuyến Html của họ để họ có thể sử dụng Intellisense (như trong FullView.cshtml).

Tất cả mọi thứ biên dịch tốt và IntelliSense đang làm việc, nhưng tôi nhận được lỗi một thời gian chạy:

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]'. 

Tôi đã đọc mà tôi có thể có thể sử dụng covarience vào loại generic của tôi để có được điều này để làm việc, nhưng tôi không chắc chắn làm thế nào để làm điều đó.

Bạn có thể vui lòng hướng dẫn tôi cách làm việc này không?

Trả lời

3

Thay đổi định nghĩa trong _Control.cshtml:

Thay đổi này @model SimpleExample<dynamic>

-@model dynamic và nó sẽ hoạt động, nhưng sẽ mất IntelliSense của SimpleExample

IntelliSense của MyViewData sẽ vẫn hoạt động.

Tôi nghĩ rằng đó là bởi vì loại động sẽ được biết đến trong thời gian chạy, nhưng các loại thuốc generic

đòi hỏi phải có thời gian đầu (có lẽ là thời gian biên dịch), vào thời điểm đó, chỉ object đang được biết đến.

+0

Điều này làm việc cho tôi, ngoại trừ tôi mất intellisense trong _Control ': (' – jjnguy

3

Bạn có thể sử dụng một đối tượng chung và sau đó, sử dụng phản chiếu, hiển thị các thuộc tính của đối tượng này (sử dụng trình trợ giúp để liệt kê các thuộc tính). Đây là phương pháp tương tự được sử dụng bởi Twitter Bootstrap cho MVC 4 (từ phần Mà mã này đã được sao chép, để thuận tiện): 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(); 
} 
Các vấn đề liên quan