如何解决自定义组件在设计器中工作,但在代码中不可见
我创建了一个从 BindingSource
派生的自定义组件,它似乎按预期工作。
当我把它放在一个 Form 上时,我可以设置所有属性,其他控件可以看到它,并且可以将它用作绑定的数据源。这一切都很好。
我的问题是,当我想在代码中访问这个组件时,代码编辑器一直告诉我没有这样的组件。
这怎么可能?
它显示在设计器中,我可以设置属性,我可以让它与设计器中的其他控件交互,并且在运行时它可以完美运行。
但是代码编辑器找不到,一直提示:
名称gttDatasource1"在当前上下文中不存在
这是什么原因造成的?如何解决?
我尝试过清理/重建
我尝试重新启动 VS
我尝试重新启动计算机
编辑
我将组件放在表单的 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
当我尝试在代码中使用这个组件时,我得到了这个:
为了证明组件实际上在表单的设计器中:
public gttDataSource(IContainer container) : this()
{
if (container == null)
{
throw new ArgumentNullException("container is null");
}
container.Add(this);
}
但这无济于事。当在表单上放置组件时或在任何其他时间,都不会调用此构造函数。
解决方法
症状:
实现自定义 CodeDomSerializer 的自定义组件,当添加到表单容器时,会生成一个对象,该对象不能从包含它的表单类访问,并且应该定义和生成组件的实例(作为 private
字段)。
该问题与自定义 CodeDomSerializer
实现有关。
实现基本 CodeDomSerializer
的自定义序列化程序必须覆盖 Deserialize()
和 Serialize()
方法。
来自文档的备注部分(注意必须,而不是应该):
要为类型实现自定义 CodeDomSerializer,您必须:
-
定义一个派生自 CodeDomSerializer 的类。
-
为序列化或反序列化方法实现方法覆盖。
-
使用 DesignerSerializerAttribute 将您的自定义 CodeDomSerializer 实现与一种组件相关联。
为了让默认序列化程序生成以标准方式配置组件/控件的代码语句,我们必须调用组件的基本序列化程序。
否则,序列化器不会执行完整的序列化,而只是使用它可以访问的类型创建一个本地对象。
因此,它不会创建关联的字段,并且在设计器中分配的属性值的序列化不会遵循标准的逻辑(该对象的属性可能会分散在 {{ 1}} 文件)。
问题中并不清楚此处发布的代码是否是完整的 Designer.cs
实现。
要按预期工作,自定义 CodeDomSerializer
必须包含 CodeDomSerializer
方法覆盖并指定应序列化的类型。
然后调用基类的默认 Serialize()
方法,生成组件的标准序列化,现在将其分配给实例字段,然后可在容器表单类中访问:
Serialize()
组件提供接受 IContainer 对象的构造函数也很重要。这用于正确处理组件,因为表单基类 (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 override object Serialize(IDesignerSerializationManager manager,object value)
{
var serializer = (CodeDomSerializer)manager.GetSerializer(typeof(gttDataSource).BaseType,typeof(CodeDomSerializer));
return serializer.Serialize(manager,value);
}
}
) 的 the default Dispose()
method 只考虑子控件,而不考虑组件。Control
会考虑此构造函数并添加 CodeDomSerialzier
:
Designer.cs
如果之前没有添加其他组件,它也会创建:
this.gttDataSource1 = new gttControls.gttDataSource(this.components);
// [...]
private gttControls.gttDataSource gttDataSource1;
因此 Form 类的 this.components = new System.ComponentModel.Container();
覆盖会处理这个:
Dispose()
简单实现:
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。