正如另一个答案中提到的,ICustomTypeDescriptor
让您可以完全控制对象的元数据,但它需要大量样板代码。对于列表绑定控件(如DataGridView
等ListView
) ,ITypedList
可以通过列表源类实现接口,这更简单,但仍需要一些编码。在这两种情况下,如果您不能创建一些基类并从它们继承所有类,那么只标记您的“不可浏览”成员会容易得多。
无论如何,还有另一种方法,有点骇人听闻,但(几乎)完全符合您的要求。该行为由我称为的自定义类提供NoBrowsableAttribute
。用法很简单:
// To turn it on
NoBrowsableAttribute.Enabled = true;
// To turn it off
NoBrowsableAttribute.Enabled = false;
请注意,当打开时,它将更改BrowsableAttribute
应用程序内所有类的默认行为。这是一个示例测试:
using System;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
namespace Samples
{
public sealed class NoBrowsableAttribute : TypeDescriptionProvider
{
public static bool Enabled
{
get { return instance.enabled; }
set { instance.enabled = value; }
}
private static readonly NoBrowsableAttribute instance = new NoBrowsableAttribute();
private bool enabled;
private NoBrowsableAttribute() : base(TypeDescriptor.GetProvider(typeof(BrowsableAttribute)))
{
TypeDescriptor.AddProvider(this, typeof(BrowsableAttribute));
}
public override Type GetReflectionType(Type objectType, object instance)
{
if (enabled && objectType == typeof(BrowsableAttribute)) return typeof(NoBrowsableAttribute);
return base.GetReflectionType(objectType, instance);
}
public static readonly BrowsableAttribute Default = BrowsableAttribute.No;
}
static class Test
{
class Person
{
public int Id { get; set; }
[Browsable(true)]
public string Name { get; set; }
[Browsable(true)]
public string Description { get; set; }
public int Age { get; set; }
}
[STAThread]
static void Main()
{
NoBrowsableAttribute.Enabled = true;
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var data = Enumerable.Range(1, 10).Select(i => new Person { Id = i, Name = "Name" + i, Description = "Description" + i }).ToList();
var form = new Form { StartPosition = FormStartPosition.CenterScreen, ClientSize = new Size(500, 300) };
var split = new SplitContainer { Dock = DockStyle.Fill, Parent = form, FixedPanel = FixedPanel.Panel2, SplitterDistance = 300 };
var dg = new DataGridView { Dock = DockStyle.Fill, Parent = split.Panel1 };
var pg = new PropertyGrid { Dock = DockStyle.Fill, Parent = split.Panel2, ToolbarVisible = false, PropertySort = PropertySort.NoSort };
dg.BindingContextChanged += (sender, e) => {
var bm = dg.BindingContext[data];
pg.SelectedObject = bm.Current;
bm.CurrentChanged += (_sender, _e) => pg.SelectedObject = bm.Current;
};
dg.DataSource = data;
Application.Run(form);
}
}
}