【问题标题】:Why Browsable attribute makes property not bindable?为什么 Browsable 属性使属性不可绑定?
【发布时间】:2010-01-12 18:24:35
【问题描述】:

我正在尝试使用System.Windows.Forms.PropertyGrid

要使属性在此网格中不可见,应将BrowsableAttribute 设置为false。 但是添加此属性会使该属性不可绑定。

示例: 创建一个新的 Windows 窗体项目,并将 TextBoxPropertyGrid 拖放到 Form1 上。使用下面的代码,TextBox 的宽度不会绑定到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;
    }
}

数据类的代码是:

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
}

如果您在 Data 中的每个属性上将 Browsable 属性切换为 true,它就会起作用。 现在看来 BindingSource 通过 Browsable Attribute 搜索数据源。

【问题讨论】:

    标签: c# .net winforms data-binding bindingsource


    【解决方案1】:

    根据更新示例更新答案:

    我在Reflector中做了一些挖掘,发现“问题”实际上在ListBindingHelper中,CurrencyManager使用,而BindingSource又使用了(这些都在@ 987654325@命名空间)。

    为了发现可绑定属性,CurrencyManager 调用 ListBindingSource.GetListItemProperties。在引擎盖下,这会调用GetListItemPropertiesByInstance(当您传入单个对象时)。该方法最后有以下代码行:

    return TypeDescriptor.GetProperties(target, BrowsableAttributeList);
    

    BrowsableAttributeList的实现是:

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

    可以看到,其实就是通过BrowsableAttribute(true)过滤属性。它可能应该改用BindableAttribute,但我猜设计师意识到每个人都已经依赖BrowsableAttribute,并决定改用那个。

    很遗憾,如果您使用BrowsableAttribute,您将无法解决此问题。您唯一的选择是执行 Marc 的建议并使用自定义 TypeConverter,或者使用此问题中的解决方案之一过滤属性网格本身:Programatically Hide Field in PropertyGrid

    【讨论】:

    • 是的,你是对的。它似乎工作。我在一个大型项目中遇到了这个问题。我会尽快写一个更好的例子。
    【解决方案2】:

    BrowsableAttribute 被许多组件模型方式用作避免包含它的机制。也许最好的选择是不添加[Browsable(false)]

    还有其他几种过滤PropertyGrid的方法,包括(越来越复杂)TypeConverterICustomTypeDescriptorTypeDescriptionProvider - 但最简单的方法可能是告诉PropertyGrid描述你的事物的属性do想要(.BrowsableAttributes),并标记其他属性。

    请注意,另一种选择是创建一个自定义选项卡 - 但根据我的经验,这是命中注定的。

    这是一个使用TypeConverter 的示例,PropertyGrid 使用它,但大多数其他绑定不使用它;它通过使用自定义类型转换器来工作,该转换器按名称排除特定属性,但您也可以使用 Attribute.IsDefined 之类的东西来进行屏蔽:

    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; }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-09
      • 1970-01-01
      • 2016-07-05
      • 1970-01-01
      • 1970-01-01
      • 2023-03-14
      相关资源
      最近更新 更多