语境
我一直在为自定义 ASP.Net Web 控件开发自定义集合编辑器/设计器。Web 控件公开了一个奇怪的层次结构,因此自定义编辑器似乎是正确的做法,可以让开发人员更轻松。
构建 ASPX 代码并使用 Web 控件可以正常工作。换句话说,事情就像PersistChildren
和ParseChildren
被照顾。
Web 控件中的属性签名如下所示:
[PersistenceMode(PersistenceMode.InnerProperty)]
[Themeable(false)]
[Browsable(false)]
public virtual DimensionsCollection Dimensions { get; internal set; }
请注意,该属性不是公开的;如果是公开的,设计师的各种事情都会出错。DimensionsCollection
是一个简单继承的类List<Dimension>
。类本身没有什么花哨的Dimension
,只是具有一些属性的东西。
仅仅因为我觉得它看起来很酷,我希望能够通过设计器中的操作来修改属性。为此,我实现了一个ControlDesigner
类并添加了一个ActionList
. 其中一项操作是打开编辑器的链接按钮:
var editor = new Editors.DimensionEditor(control.Dimensions);
if (editor.ShowDialog() == DialogResult.OK)
{ /* SEE BELOW */ }
编辑器本身是一个窗口窗体,它接受一个List<Dimension>
构造函数参数并修改集合。
问题
当我使用此代码时,我可以看到编辑器工作正常,并且控件集合在“设计器”视图中更新。如果我多次打开编辑器,状态会发生变化,这意味着在内存中的某个地方,状态会被编辑器更新。
但是,如果我转到 ASPX 代码,我可以看到维度不再存在。因此,简而言之,问题是我必须以某种方式告诉 Visual Studio 将属性写入/序列化/持久化到 ASPX 文件中。(就这么简单……)
奇怪的是,我在任何地方都找不到如何做到这一点......即使正常人CollectionEditor
似乎能够做到这一点(不幸的是我不能继承)
我尝试过的一些事情
对于其他属性,我注意到您必须使用类似的东西,但这似乎不起作用。在标记为“见下文”的点输入代码,或者在某些情况下输入从该点调用的设计器中的辅助调用:
PropertyDescriptor pd = TypeDescriptor.GetProperties(base.Component)["Dimensions"];
// use setter with internal property -> no effect
// this.OnComponentChanged(this, new ComponentChangedEventArgs(this.Component, pd, null, newdim)); -> no effect
// use getter to obtain list -> populate that using another list that's created in the editor
我能理解为什么它不起作用;显然有人必须告诉 Visual Studio 该属性已更改...我只是不知道该怎么做。