2010-01-12 43 views
5

Tôi đang cố gắng sử dụng System.Windows.Forms.PropertyGrid.Tại sao thuộc tính Có thể duyệt web làm cho thuộc tính không bị ràng buộc?

Để làm cho thuộc tính không hiển thị trong lưới này, bạn nên sử dụng BrowsableAttribute đặt thành false. Nhưng việc thêm thuộc tính này làm cho thuộc tính không bị ràng buộc.

Ví dụ: Tạo một Windows mới Forms dự án, và thả một TextBoxPropertyGrid vào Form1. Sử dụng mã bên dưới, độ rộng của TextBox không được ràng buộc để Data.Width:

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 

     Data data = new Data(); 
     data.Text = "qwe"; 
     data.Width = 500; 

     BindingSource bindingSource = new BindingSource(); 
     bindingSource.Add(data); 

     textBox1.DataBindings.Add("Text", bindingSource, "Text", true, 
      DataSourceUpdateMode.OnPropertyChanged); 
     textBox1.DataBindings.Add("Width", bindingSource, "Width", true, 
      DataSourceUpdateMode.OnPropertyChanged); 

     propertyGrid1.SelectedObject = data; 
    } 
} 

Mã cho lớp dữ liệu là:

public class Data : IBindableComponent 
{ 
    public event EventHandler TextChanged; 
    private string _Text; 
    [Browsable(true)] 
    public string Text 
    { 
     get 
     { 
      return _Text; 
     } 
     set 
     { 
      _Text = value; 
      if (TextChanged != null) 
       TextChanged(this, EventArgs.Empty); 
     } 
    } 

    public event EventHandler WidthChanged; 
    private int _Width; 
    [Browsable(false)] 
    public int Width 
    { 
     get 
     { 
      return _Width; 
     } 
     set 
     { 
      _Width = value; 
      if (WidthChanged != null) 
       WidthChanged(this, EventArgs.Empty); 
     } 
    } 

    #region IBindableComponent Members 

    private BindingContext _BindingContext; 
    public BindingContext BindingContext 
    { 
     get 
     { 
      if (_BindingContext == null) 
       _BindingContext = new BindingContext(); 

      return _BindingContext; 
     } 
     set 
     { 
      _BindingContext = value; 
     } 
    } 

    private ControlBindingsCollection _DataBindings; 
    public ControlBindingsCollection DataBindings 
    { 
     get 
     { 
      if (_DataBindings == null) 
       _DataBindings = new ControlBindingsCollection(this); 

      return _DataBindings;  
     } 
    } 

    #endregion 

    #region IComponent Members 

    public event EventHandler Disposed; 

    public System.ComponentModel.ISite Site 
    { 
     get 
     { 
      return null; 
     } 
     set 
     { 

     } 
    } 

    #endregion 

    #region IDisposable Members 

    public void Dispose() 
    { 
     throw new NotImplementedException(); 
    } 

    #endregion 
} 

Nếu bạn chuyển đổi các thuộc tính Có thể xem là true trên tất cả các bất động sản trong Dữ liệu hoạt động. Bây giờ có vẻ như nguồn dữ liệu tìm kiếm BindingSource theo Thuộc tính có thể duyệt.

Trả lời

6

câu trả lời Cập nhật dựa trên bản cập nhật Ví dụ:

tôi đã thực hiện một số đào trong Reflector và phát hiện ra rằng "vấn đề" thực sự là trong ListBindingHelper, được sử dụng bởi CurrencyManager, đó là lần lượt được sử dụng bởi BindingSource (đây là tất cả trong không gian tên System.Windows.Forms).

Để khám phá các thuộc tính có thể ràng buộc, số CurrencyManager gọi ListBindingSource.GetListItemProperties. Dưới mui xe, điều này kêu gọi GetListItemPropertiesByInstance (khi bạn vượt qua trong một đối tượng duy nhất). Đó là phương pháp có dòng mã sau đây vào cuối file:

return TypeDescriptor.GetProperties(target, BrowsableAttributeList); 

Và việc thực hiện BrowsableAttributeList là:

private static Attribute[] BrowsableAttributeList 
{ 
    get 
    { 
     if (browsableAttribute == null) 
     { 
      browsableAttribute = new Attribute[] { new BrowsableAttribute(true) }; 
     } 
     return browsableAttribute; 
    } 
} 

Bạn có thể thấy rằng nó là, trên thực tế, lọc thuộc tính bởi BrowsableAttribute(true). Nó có lẽ nên được sử dụng BindableAttribute thay vào đó, nhưng tôi đoán là các nhà thiết kế nhận ra rằng tất cả mọi người đã được tùy thuộc vào BrowsableAttribute và quyết định sử dụng một thay thế.

Rất tiếc, bạn sẽ không thể giải quyết vấn đề này nếu bạn sử dụng BrowsableAttribute. Các tùy chọn duy nhất của bạn là thực hiện những gì Marc đề xuất và sử dụng tùy chỉnh TypeConverter hoặc tự lọc lưới thuộc tính bằng cách sử dụng một trong các giải pháp trong câu hỏi này: Programatically Hide Field in PropertyGrid.

+0

Vâng, bạn nói đúng. Dường như nó hoạt động. Tôi có vấn đề này trong một dự án larg. Tôi sẽ cố gắng viết một ví dụ tốt hơn sớm thôi. – bodziec

3

BrowsableAttribute được nhiều kiểu mô hình sử dụng làm cơ chế để tránh bị bao gồm. Có lẽ tùy chọn tốt nhất là không thêm [Browsable(false)].

Có một số cách khác để lọc PropertyGrid, bao gồm (trong việc tăng độ phức tạp) TypeConverter, ICustomTypeDescriptor, TypeDescriptionProvider - nhưng đơn giản nhất có lẽ là để nói PropertyGrid các thuộc tính mô tả điều bạn làm muốn (.BrowsableAttributes), và đánh dấu Các tài sản khác.

Lưu ý rằng tùy chọn khác là tạo tab tùy chỉnh - nhưng đó là lần truy cập trong trải nghiệm của tôi.

Dưới đây là ví dụ sử dụng TypeConverter, được sử dụng bởi PropertyGrid, nhưng không phải bởi hầu hết các kết buộc khác; nó hoạt động bằng cách có một loại chuyển đổi tùy chỉnh loại trừ một thuộc tính cụ thể theo tên, nhưng bạn cũng có thể sử dụng một cái gì đó như Attribute.IsDefined để làm mặt nạ:

using System.Windows.Forms; 
using System; 
using System.Linq; 
using System.ComponentModel; 
static class Program 
{ 
    [STAThread] 
    static void Main() 
    { 
     Application.EnableVisualStyles(); 
     Data data = new Data { Name = "the name", Value = "the value" }; 
     using (Form form = new Form 
     { 
      Controls = 
      { 
       new PropertyGrid { 
        Dock = DockStyle.Fill, 
        SelectedObject = data 
       }, 
       new TextBox { 
        Dock = DockStyle.Bottom, 
        DataBindings = { {"Text", data, "Value"}, } 
       }, 
       new TextBox { 
        Dock = DockStyle.Bottom, 
        DataBindings = { {"Text", data, "Name"}, } 
       } 
      } 
     }) 
     { 
      Application.Run(form); 
     }   
    } 
} 
[TypeConverter(typeof(DataConverter))] 
class Data 
{ 
    class DataConverter : ExpandableObjectConverter 
    { 
     public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) 
     { 
      var props = base.GetProperties(context, value, attributes); 
      return new PropertyDescriptorCollection(
       (from PropertyDescriptor prop in props 
       where prop.Name != "Value" 
       select prop).ToArray(), true); 
     } 
    } 
    public string Value { get; set; } 
    public string Name { get; set; } 
} 
Các vấn đề liên quan