我在GUI项目中使用的库中定义了一个类Foo。 GUI项目允许在System.Windows.Forms.PropertyGrid
。
为了在PropertyGrid
中编辑Foo类的实例,我必须为Foo的属性设置几个属性,例如Browsable
。
但是,我不想在Foo中设置这些属性,因为它所在的库应该只包含在代码中使用Foo所需的东西(而不是在GUI中)。
如何获得PropertyGrid
友好版的Foo?
我已经尝试从它继承(命名为FooDesignable)并使用所需属性隐藏其属性。但是,直到我发现Foo正在使用库项目的其他自定义类,然后我也不得不影子,并且更改Foo中的现有属性以返回XxxDesignable类型时,这种方法效果不好。
我在这里走到了尽头吗?或者我只是在想它呢?
答案 0 :(得分:1)
您可以做的是重新使用我在这个问题的答案中描述的DynamicTypeDescriptor
课程:PropertyGrid Browsable not found for entity framework created property, how to find it?
就像这样:
public Form1()
{
InitializeComponent();
DynamicTypeDescriptor dt = new DynamicTypeDescriptor(typeof(MyBeautifulClass));
// initialize the class the way you want
MyBeautifulClass c = new MyBeautifulClass();
c.MyProperty = "hello world";
// we need to replace a property by another version, so let's remove the existing one
dt.RemoveProperty("MyProperty");
// create a new similar property with a new editor and the current value
dt.AddProperty(
typeof(string), // type
"MyProperty", // name
c.MyProperty, // value
"My Property", // display name
"My Property Description", // description
"My Category", // category
false, // has default value?
null, // default value
false, // readonly?
typeof(MyEditor)); // editor
// create a wrapped object from the original one.
// unchanged properties will keep their current value
var newObject = dt.FromComponent(c);
// hook on value change
newObject.PropertyChanged += (sender, e) =>
{
// update the original object
// note: the code could be made more generic
c.MyProperty = newObject.GetPropertyValue<string>(e.PropertyName, null);
};
propertyGrid1.SelectedObject = newObject;
}
public class MyBeautifulClass
{
public string MyProperty { get; set; }
}
// this stupid sample editor puts a current string in upper case... :-)
public class MyEditor : UITypeEditor
{
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.Modal;
}
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
return value == null ? value : value.ToString().ToUpper();
}
}
答案 1 :(得分:0)
我认为你有正确的想法来创建另一种类型,但FooDesigner
应该是一个包装器,而不是从Foo
继承。这样,您就可以将复杂对象包装在自己的包装器类型中。如果要包装很多类,这可能会变得乏味。您可能希望查看T4模板以帮助生成包装类的骨架。这是一个例子:
class FooDesigner
{
private Foo foo;
public FooDesigner(Foo foo)
{
this.foo = foo;
}
public int Prop1
{
get { return foo.Prop1; }
set { foo.Prop1 = value; }
}
public BarDesigner Bar { get { return new BarDesigner(foo.Bar); } }
}
class BarDesigner
{
private Bar bar;
public BarDesigner(Bar bar)
{
this.bar = bar;
}
public string Prop2
{
get { return bar.Prop2; }
set { bar.Prop2 = value; }
}
}