2012-09-17 32 views
5

Tôi có một mô hình như dưới đây:Làm thế nào để truy cập vào C# mô hình thuộc tính trong EditorFor

public class CreateStockcheckJobModel 
{ 
    [Engineer(true)] 
    public EngineerModel Engineer { get; set; } 
} 

Tôi render các Engineer tài sản trong một View<CreateStockcheckJobModel> sử dụng Html.EditorFor(m => m.Engineer, "EngineerEditor").

Làm cách nào để truy cập giá trị trong thuộc tính Engineer (trong trường hợp này là true) từ trong mã trong chế độ xem một phần của tôi (EngineerEditor.ascx)?


Dưới đây là mã biên tập của tôi

<%@ Control Language="C#" Inherits="ViewUserControl<EngineerModel>" %> 
<% if (PropertyImRenderingHasAttributeWithTrueBooleanValue) // What goes here? 
    { %> 
<p>Render one thing</p> 
<% } 
    else 
    { %> 
<p>Render another thing</p> 
<% } %> 

Tôi nhận thức được phản ánh, tuy nhiên tôi không chắc chắn làm thế nào để sử dụng nó như là thuộc tính không được thêm vào lớp EngineerModel nó thêm vào Engineer thuộc tính của lớp CreateStockcheckJobModel. Nếu tôi có thể nhận được PropertyInfo mà tôi đang hiển thị từ mã trình chỉnh sửa thì tôi sẽ được sắp xếp, nhưng tôi không biết cách lấy thông tin đó. Nếu tôi đi xuống đường liệt kê tất cả các thuộc tính trong lớp CreateStockcheckJobModel thì tôi sẽ gặp sự cố nếu tôi có nhiều hơn một thuộc tính EngineerModel (một thuộc tính có thể có thuộc tính là True, một thuộc tính khác có thể có False).

+0

Bạn muốn nhận gì? Dường như với tôi, rằng bạn làm sai để đạt được mục tiêu của bạn –

+0

Về cơ bản, nó hiển thị danh sách các kỹ sư có thể chọn. Tôi muốn thuộc tính kiểm soát danh sách các kỹ sư có sẵn. –

+0

Tôi nghĩ đó là một sự chấp thuận hợp lý vì nó có vẻ là thuộc tính 'DisplayFormat' đang làm (tức là thay đổi cách điều khiển/trình soạn thảo được hiển thị dựa trên dữ liệu trong thuộc tính) –

Trả lời

7

Điều này có thể được thực hiện dễ dàng trong ASP.NET MVC 3 và sau đó bằng cách thực hiện các giao diện IMetadataAware vào tùy chỉnh của bạn EngineerAttribute:

public class EngineerAttribute : Attribute, IMetadataAware 
{ 
    public EngineerAttribute(bool isFoo) 
    { 
     IsFoo = isFoo; 
    } 

    public bool IsFoo { get; private set; } 

    public void OnMetadataCreated(ModelMetadata metadata) 
    { 
     metadata.AdditionalValues["IsFoo"] = IsFoo; 
    } 
} 

và sau đó bên trong mẫu:

<%@ Control Language="C#" Inherits="ViewUserControl<EngineerModel>" %> 
<% 
    var isFoo = (bool)ViewData.ModelMetadata.AdditionalValues["IsFoo"]; 
%> 
<% if (isFoo) { %> 
    <p>Render one thing</p> 
<% } else { %> 
    <p>Render another thing</p> 
<% } %> 

Thật không may này giao diện không tồn tại trong ASP.NET MVC 2.Để đạt được các chức năng tương tự bạn có thể viết một nhà cung cấp siêu dữ liệu tùy chỉnh:

public class MyMetadataProvider : DataAnnotationsModelMetadataProvider 
{ 
    protected override ModelMetadata CreateMetadata(
     IEnumerable<Attribute> attributes, 
     Type containerType, 
     Func<object> modelAccessor, 
     Type modelType, 
     string propertyName 
    ) 
    { 
     var metadata = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName); 
     var engineer = attributes.OfType<EngineerAttribute>().FirstOrDefault(); 
     if (engineer != null) 
     { 
      metadata.AdditionalValues["IsFoo"] = engineer.IsFoo; 
     } 
     return metadata; 
    } 
} 

mà bạn sẽ đăng ký trong Application_Start của bạn để thay thế mặc định một:

ModelMetadataProviders.Current = new MyMetadataProvider(); 

Và bây giờ bạn có thể truy cập vào siêu dữ liệu này trong mẫu của bạn giống như cách tôi đã trình bày trước đó, sử dụng ViewData.ModelMetadata.AdditionalValues["IsFoo"]. Rõ ràng là bạn có thể đặt một đối tượng tùy ý phức tạp bên trong thuộc tính AdditionalValues, không chỉ là boolean.

Bạn cũng có thể tìm thấy following article hữu ích về siêu dữ liệu.

1

LƯU Ý: Dưới đây là cách có thể thực hiện điều này nhưng sử dụng IMetadataAware như được mô tả trong câu trả lời được chấp nhận là cách tốt hơn nhiều. Nó thường tốt hơn để tránh sự phản chiếu nếu bạn có thể.

Bạn chỉ có thể thực hiện việc này thông qua phản ánh. Đây là một good example về cách thực hiện điều này cho các thuộc tính phương pháp.

Mã ví dụ cho nhận được giá trị của EngineerAttribute về sở hữu Engineer:

PropertyInfo pi = Model.GetType().GetProperty("Engineer"); 
EngineerAttribute a = 
    System.Attribute.GetCustomAttribute(pi, typeof(EngineerAttribute)); 

Mã ví dụ cho nhận được tất cả tài sản mà có thuộc tính [Engineer(true)]:

var t = Model.GetType(); 
var engineerProperties = 
    from p in t.GetProperties() 
    let ca = System.Attribute.GetCustomAttribute(p, typeof(EngineerAttribute)) 
    where ca != null && ca.BooleanProperty == true 
    select p; 

Và khi bạn có các đặc tính này, bạn có thể sử dụng quá tải EditorFor cho phép bạn chỉ định dữ liệu chế độ xem bổ sung, sau đó bạn có thể sử dụng trong chế độ xem phụ của mình:

Html.EditorFor(m => m.Engineer, new { IsEngineer = isEngineer }); 
+0

gặp khó khăn khi tìm ra thuộc tính nào để lấy thuộc tính như trong trình soạn thảo, tôi chỉ có kiểu 'EngineerModel' không phải kiểu kèm theo và thuộc tính (tức là thuộc tính không nằm trong' EngineerModel' trên thuộc tính có thể xảy ra 'EngineerModel'). –

+0

Với chỉnh sửa của bạn, vấn đề của tôi là trong trình soạn thảo mô hình có kiểu 'EngineerModel' và thuộc tính không có trong mô hình, nó thuộc về thuộc tính của mô hình kèm theo. Rõ ràng tên thuộc tính có thể thay đổi và có thể có nhiều thuộc tính với kiểu 'EngineerModel' (vì vậy tôi không thể lấy kiểu mô hình kèm theo và tìm thuộc tính của kiểu' EngineerModel'). –

+0

Tôi chỉ đọc nhận xét về câu hỏi và những gì bạn thực sự muốn là liệt kê tất cả các thuộc tính có '[Kỹ sư (đúng)]'? –