我已经创建了一个自定义组件,从BindingSource
派生,它似乎按预期工作。
当我把它放在一个窗体上时,我可以设置所有的属性,其他控件可以看到它,并可以将它用作绑定的数据源。
我的问题是,当我想在代码中访问这个组件时,代码编辑器一直告诉我没有这样的组件。
这怎么可能呢?
它显示在设计器中,我可以设置属性,我可以让它与设计器中的其他控件交互,并且在运行时它可以完美地工作。
但是代码编辑器找不到它,它一直在说:
当前上下文中不存在名称“gttDatasource 1
什么原因会导致这种情况?如何解决?
我试过清理/重建
我尝试重新启动VS
我试着重启电脑
编辑
Form I的Designer.cs
部分将组件掉落在:
namespace Test_app
{
partial class FormLogSCSSalesInvoiceList
{
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormLogSCSSalesInvoiceList));
gttControls.gttDataSource gttDataSource1 = new gttControls.gttDataSource();
自定义组件位于Designer.cs
自定义组件部分代码
namespace gttControls
{
internal class gttDataSourceCodeDomSerializer : CodeDomSerializer
{
public override object Deserialize(IDesignerSerializationManager manager, object codeObject)
{
CodeDomSerializer baseClassSerializer = (CodeDomSerializer)manager.GetSerializer(typeof(gttDataSource).BaseType, typeof(CodeDomSerializer));
var Result = baseClassSerializer.Deserialize(manager, codeObject);
((gttDataSource)Result).CorrectTableColumns();
return Result;
}
}
public delegate void OnActiveChangedHandler(object sender, EventArgs e);
public delegate void OnBeforeUpdateHandler(object sender, EventArgs e);
[DesignerSerializer(typeof(gttDataSourceCodeDomSerializer), typeof(CodeDomSerializer))]
public partial class gttDataSource : BindingSource
{
private readonly gttDataTable _gttDataTable;
private GttTableProperties _gttTableProperties;
private Collection<gttDataTableColumn> _columns = new Collection<gttDataTableColumn>();
private bool _active = false;
private readonly bool _refreshSchema = false;
public event ActiveChangedHandler ActiveChanged;
public event BeforeUpdateHandler BeforeUpdate;
public gttDataSource()
{
_gttTableProperties = new GttTableProperties(this);
_gttDataTable = new gttDataTable();
DataSource = _gttDataTable.Table;
_gttDataTable.BeforeUpdate += _gttDataTable_BeforeUpdate;
}
}
}
编辑2
当我尝试在代码中使用这个组件时,我得到了这个:
为了证明组件实际上在表单的设计器中:
编辑3
我在评论中添加了一个ctor:
public gttDataSource(IContainer container) : this()
{
if (container == null)
{
throw new ArgumentNullException("container is null");
}
container.Add(this);
}
但这并没有帮助。当在窗体上放置组件时,或在任何其他时间,都不会调用此构造函数。
1条答案
按热度按时间mwg9r5ms1#
症状:
实现自定义CodeDomSerializer的自定义组件,当添加到表单容器时,会生成一个无法从包含它的Form类访问的Object,并且 * 应该 * 定义和生成组件的示例(作为
private
字段)。此问题与自定义
CodeDomSerializer
实现有关。实现基
CodeDomSerializer
的自定义序列化程序必须覆盖**Deserialize()
和Serialize()
**方法。来自文档的备注部分(注意 * 必须 *,而不是 * 应 *):
若要为类型实现自定义CodeDomSerializer,必须:
为了让默认序列化程序生成以标准方式配置Component / Control的代码语句,我们必须调用该组件的基序列化程序。
否则,序列化程序不会执行完整的序列化,而只是使用它可以访问的Type创建一个局部对象。
因此,它不会创建关联的Field,并且在Designer中分配的Property值的序列化也不会遵循标准的 * 逻辑 *(此对象的Properties可能分散在
Designer.cs
文件中)。在问题中,不清楚这里发布的代码是否是完整的
CodeDomSerializer
实现。要按预期工作,自定义
CodeDomSerializer
必须包含Serialize()
方法覆盖,并指定应序列化的类型。然后调用基类的默认
Serialize()
方法,生成Componenent的标准序列化,该序列化现在被分配给示例Field,然后可以在Container Form类中访问:Components提供一个接受IContainer对象的构造函数也很重要,因为窗体基类(
Control
)的默认Dispose()
方法只考虑子控件,而不考虑Components。CodeDomSerialzier
考虑了这个构造函数,并在Designer.cs
中添加了:如果之前没有添加其他组件,则还会创建:
所以Form类的
Dispose()
覆盖可以解决这个问题:简单实施: