2012-05-07 45 views
7

Tôi muốn hiển thị nhiều phiên bản của một lớp trong số PropertyGrid của mình. Lớp học trông giống như sau:Thuộc tính chỉ đọc PropertyGrid ở cấp đối tượng

public class Parameter 
{ 
    [Description("the name")] 
    public string Name { get; set; } 

    [Description("the value"), ReadOnly(true)] 
    public string Value { get; set; } 

    [Description("the description")] 
    public string Description { get; set; } 
} 

Tôi có nhiều trường hợp trong lớp đó là TreeView. Khi tôi chọn một trong số chúng trong số TreeView của mình, các thuộc tính sẽ hiển thị trong số PropertyGrid như mong đợi. Cho đến nay rất tốt, nhưng tôi muốn tùy chỉnh hành vi này theo cách sau:

Đối với từng trường hợp, tôi muốn có thể ngăn người dùng sửa đổi một thuộc tính cụ thể. Bằng cách đặt ReadOnly(true) trong lớp học của tôi (như bạn có thể thấy trong ví dụ trên), tất cả các thuộc tính Value sẽ bị tắt trên cấp lớp.

Sau khi một số nghiên cứu tôi thấy các giải pháp sau đó mang lại cho tôi cơ hội để bật/tắt một tài sản cụ thể tại thời gian chạy:

PropertyDescriptor descriptor = TypeDescriptor.GetProperties(this)["Value"]; 

ReadOnlyAttribute attr = 
     (ReadOnlyAttribute)descriptor.Attributes[typeof(ReadOnlyAttribute)]; 

FieldInfo isReadOnly = attr.GetType().GetField(
     "isReadOnly", BindingFlags.NonPublic | BindingFlags.Instance); 

isReadOnly.SetValue(attr, false); 

Cách tiếp cận này chỉ hoạt động tốt nhưng tiếc là cũng trên chỉ lớp cấp. Điều này có nghĩa là nếu tôi đặt Value củathành false, tất cả trong số Parameter -khối đối tượng của mình có thể ghi Value thuộc tính có thể ghi. Nhưng tôi muốn điều này chỉ trên một đối tượng cụ thể (do đó đối tượng cấp). Tôi thực sự không muốn tạo các lớp riêng biệt cho các thuộc tính read/write và readonly.

Khi tôi hết ý tưởng, trợ giúp của bạn được đánh giá cao :)

Cảm ơn bạn trước!

EDIT: Tôi cần các thuộc tính chỉ đọc được chuyển sang màu xám, vì vậy người dùng có thể thấy rằng nó không được phép hoặc có thể chỉnh sửa chúng.

Trả lời

4

EDIT: Liên kết bài viết đã được gỡ bỏ (Tôi hy vọng chỉ là tạm thời). Bạn có thể phạt một giải pháp thay thế khả thi trong câu trả lời cho How to add property-level Attribute to the TypeDescriptor at runtime?. Về cơ bản bạn phải thêm (tại thời gian chạy) ReadOnlyAttribute thông qua một TypeDescriptor cho thuộc tính đó.


Hãy xem cũ nhưng đẹp article on CodeProject này, nó có chứa rất nhiều công cụ hữu ích cho PropertyGrid.

Về cơ bản bạn cung cấp một lớp hoặc một đại biểu sẽ được sử dụng để lấy các thuộc tính của thuộc tính của bạn. Bởi vì nó sẽ được gọi đi qua thể hiện của đối tượng bạn muốn nhận các thuộc tính cho sau đó bạn sẽ có thể trả về (hoặc không) là ReadOnlyAttribute với một cơ sở cho mỗi đối tượng.Ngắn gọn: áp dụng PropertyAttributesProviderAttribute cho thuộc tính của bạn, viết nhà cung cấp của riêng bạn và thay thế các thuộc tính từ bộ sưu tập PropertyAttributes dựa trên chính đối tượng đó (và không phải trên lớp)

+0

Tôi đã đọc toàn bộ tài liệu nhưng vẫn không hiểu ý tưởng của bạn. Bạn có thể cung cấp cho tôi một ví dụ mã nhỏ để làm cho nó rõ ràng hơn một chút không? Cảm ơn bạn đã dành thời gian :) –

+0

Xem đoạn * Sử dụng động * trong bài viết đó. Một thời gian ngắn: áp dụng một PropertyAttributesProviderAttribute cho tài sản của bạn, viết nhà cung cấp của riêng bạn và thay thế các thuộc tính từ bộ sưu tập PropertyAttributes dựa trên chính đối tượng đó (và không phải trên lớp). –

+0

Như tôi có thể thấy trong mã nguồn, điều này đòi hỏi phải sử dụng các tác giả tùy chỉnh PropertyGrid thực hiện để làm cho nó hoạt động? Trong trường hợp của tôi, tôi phải sử dụng một PropertyGrid hiện có trong một DLL (mà tôi không thể sửa đổi). –

1

Bạn có thể bọc đối tượng bằng bộ mô tả kiểu tùy chỉnh, nhưng tôi nghĩ điều đó sẽ quá mức cần thiết vì bạn phải tạo lớp mới có nguồn gốc từ typedescriptor.

Vì vậy, một giải pháp đơn giản nhất là nên có một lá cờ, một cái gì đó như:

public class Parameter 
{ 
    private string thevalue; 

    [Browsable(false)] 
    public bool CanEditValue { get; set; } 

    [Description("the name")] 
    public string Name { get; set; } 

    [Description("the description")] 
    public string Description { get; set; } 

    [Description("the value"), ReadOnly(true)] 
    public string Value { 
     get { return this.thevalue; } 
     set { if (this.CanEditValue) this.thevalue = value; } 
    } 
} 
+0

Xin chào Jaime, đề xuất của bạn với thuộc tính gấp đôi sẽ được chấp nhận vì nó thực sự đơn giản. Tôi đã thử điều này và không may kiểm tra trong setter không vô hiệu hóa chỉnh sửa tài sản như ReadOnly (true) ... do đó, nó không phải là grayed-out. người dùng sẽ nghĩ rằng nó có thể thay đổi nhưng đầu vào của họ sẽ bị loại bỏ. bất kỳ ý tưởng ít phức tạp nào khác? :) –

+0

Tôi sợ rằng bạn lựa chọn duy nhất là lấy được một bộ mô tả thuộc tính và thực hiện điều kiện getReadOnly có điều kiện. –

Các vấn đề liên quan