2010-08-24 52 views
7

Tôi yêu PropertyGrid, tốt, ít nhất là khái niệm đằng sau nó - sử dụng sự phản ánh và các thuộc tính để chỉnh sửa các đối tượng của bạn mà không cần viết nhiều mã UI.PropertyGrid lựa chọn thay thế

Sự phấn khích của tôi đã chết khá nhanh, mặc dù giao dịch PropertyGrid mặc định với tính năng hoàn toàn không sử dụng WinForms. Vâng, nó là tốt để chỉnh sửa các đối tượng đơn giản và như vậy, nhưng đó là như xa như nó đi.

  • Nó không hiển thị UITypeEditors thích hợp cho thuộc tính động có loại "Đối tượng".
  • Ngay khi đối tượng của bạn chứa các bộ sưu tập, bạn có thể chỉnh sửa chúng bằng cái gọi là CollectionEditor. Tuy nhiên, nó sẽ không kích hoạt sự kiện PropertyValueChanged. Vì vậy, một khi bạn cần phải thêm chức năng hoàn tác, bạn đang say.
  • Và tôi vẫn chưa tìm thấy cách thanh lịch để thêm xác thực cho CollectionEditor.
  • Nó cũng có vấn đề để thực hiện hoàn tác nếu bạn có nhiều đối tượng được chọn, bởi vì trong trường hợp đó sự kiện PropertyValueChanged args ChangedItem là null.

Tôi sớm tìm thấy chính mình bằng văn bản hack để giải quyết những vấn đề đó với ít hơn kết quả dễ chịu.

Bạn sẽ làm gì? Có một giải pháp thanh lịch cho ít nhất ba vấn đề đầu tiên không? Có một tài sản thay thế không? Tốt nhất là miễn phí & mà không có PInvokes?

+0

Đối với tài sản được đổi cho bộ sưu tập. Tôi sẽ lo lắng nếu có điều gì đó thay đổi tham chiếu của cá thể bộ sưu tập. Hãy suy nghĩ về nó. – leppie

Trả lời

5

Rất nhiều sự sang trọng của PropertyGrid xuất phát từ sự đơn giản của nó. Trên tất cả, nó được thiết kế để chơi tốt đẹp với Visual Studio, và tôi mong đợi để xem nó được sử dụng chủ yếu trong tùy chỉnh UITypeEditor s và phần mở rộng, hơn là trong mã ứng dụng.

Có lẽ các đối tượng bạn đang gắn vào PropertyGrid là các lớp thiết kế của riêng bạn? Tôi đã tìm thấy rằng, để sử dụng tốt lưới điện của tài sản, bạn phải trang trí rất nhiều các lớp và các thành viên của bạn với các thuộc tính.

Bạn có thể tìm thấy một số niềm vui khi viết các lớp con của riêng bạn CollectionEditor (và các loại trình chỉnh sửa khác) và đính kèm chúng vào các thành viên lớp học sử dụng thuộc tính [Editor] - nếu bạn có thể đính kèm thuộc tính này vào thuộc tính động của mình, bạn có thể buộc sử dụng của một trình soạn thảo cụ thể.

Cách duy nhất tôi có thể nghĩ là thêm xác thực vào CollectionEditor là ghi đè phương thức CreateCollectionForm(), trả lại phiên bản của lớp con tùy chỉnh của riêng bạn là CollectionEditor.CollectionForm. Có khả năng bạn sẽ có thể kích hoạt sự kiện thay đổi từ đây.

Thật không may tất cả những gì tôi có thể làm là gật đầu và đồng ý với xác nhận về việc triển khai hoàn tác. Bạn có thể phải nghỉ mát để 'sao lưu' các đối tượng bị ảnh hưởng thông qua nhân bản hoặc tuần tự hóa để thực hiện hoàn tác.

Tôi đã thấy các lựa chọn thay thế cho điều khiển lưới thuộc tính tích hợp sẵn nhưng chúng tồn tại chủ yếu để cung cấp các kiểu trực quan khác nhau.

2

Nếu ai đó quan tâm - đây là giải pháp cho sự cố PropertyValueChanged mô phỏng thay đổi bằng cách gọi hàm MemberwiseClone của System.Object nếu PropertyValueChanged của CollectionEditor đã bị sa thải ...

public class FixedCollectionEditor : CollectionEditor 
{   
    bool modified; 

    public FixedCollectionEditor(Type type) 
     : base(type) 
    { } 

    public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, IServiceProvider provider, object value) 
    {    
     value = base.EditValue(context, provider, value); 
     if (value != null && modified) 
     { 
      value = value.GetType() 
       .GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic) 
       .Invoke(value, new object[] { });     
     } 
     modified = false; 
     return value; 
    } 

    protected override CollectionForm CreateCollectionForm() 
    { 
     CollectionForm collectionForm = base.CreateCollectionForm(); 

     foreach (Control table in collectionForm.Controls) 
     { 
      if (!(table is TableLayoutPanel)) { continue; } 
      foreach (Control c1 in table.Controls) 
      { 
       if (c1 is PropertyGrid) 
       { 
        PropertyGrid propertyGrid = (PropertyGrid)c1; 
        propertyGrid.PropertyValueChanged += new PropertyValueChangedEventHandler(GotModifiedHandler); 
       } 
       if (c1 is TableLayoutPanel) 
       { 
        foreach (Control c2 in c1.Controls) 
        { 
         if (!(c2 is Button)) { continue; } 
         Button button = (Button)c2; 
         if (button.Name == "addButton" || button.Name == "removeButton") 
         { 
          button.Click += new EventHandler(GotModifiedHandler); 
          if (button.ContextMenuStrip != null) 
          { 
           button.ContextMenuStrip.ItemClicked += new ToolStripItemClickedEventHandler(GotModifiedHandler); 
          } 
         } 
        } 
       } 
      } 
     } 
     return collectionForm; 
    } 

    void GotModifiedHandler(object sender, EventArgs e) 
    { 
     modified = true; 
    } 
} 
1

Visualhint bán thay thế cho lưới thuộc tính có thể hữu ích. Vì tôi chưa bao giờ sử dụng nó trong một dự án thực sự, tôi không biết nó hoạt động tốt như thế nào.