我必须遗漏一些非常明显的东西。我对C#很陌生,但已经用C / C ++编程多年了,很抱歉,如果它显得非常明显;)
[请参阅针对较新问题进行编辑]
我正在尝试创建一个包含UserControl的节点。我有控件出现在WinForm设计器中,我可以添加节点。但是,当我尝试运行代码时,我收到以下错误:
属性“节点”的代码生成失败。错误是:'类型 程序集'应用程序中的App.Node',版本= 1.0.0.0,文化=中立, PublicKeyToken = null'未标记为可序列化。
然后我添加的节点都没有出现。
这开始让我发疯,因为据我所知,它被标记为可序列化。
节点定义如下:
[Serializable]
public class Node : MarshalByRefObject
{
public Node()
{
}
public Node( String text )
{
this.Text = text;
this.Checked = false;
this.Complete = false;
}
public String Text { get; set; }
public bool Checked { get; set; }
public bool Complete { get; set; }
public bool Selected { get; set; }
};
然后我按如下方式定义“收藏”:
[Serializable]
public class NodeCollection : List< Node >
{
public NodeCollection() :
base()
{
}
};
集合和节点本身都设置了“Serializable”属性,如您所见。
错误中提到的Nodes属性定义如下
private NodeCollection mNodes = new NodeCollection();
[Category( "Behavior" )]
[Description( "Nodes" )]
public NodeCollection Nodes
{
get
{
return mNodes;
}
}
所以有谁知道我在这里做错了什么?
编辑:为响应Archeg的评论,这是我的UserControl:
public partial class Control : UserControl
{
public Control()
{
InitializeComponent();
}
protected override void OnPaint( PaintEventArgs pe )
{
Graphics graph = pe.Graphics;
int rowHeight = Font.Height + 2;
if ( Nodes != null )
{
int yPos = 0;
foreach( Node node in this.Nodes )
{
// Calculate my various bounding boxes.
Rectangle nodeBounds = new Rectangle( Bounds.Left, yPos, Bounds.Width, rowHeight );
Rectangle lightBounds = new Rectangle( Bounds.Right - Font.Height, yPos, rowHeight, rowHeight );
Rectangle spannerBounds = new Rectangle( lightBounds.Left - Font.Height, yPos, rowHeight, rowHeight );
Rectangle checkBoxBound = new Rectangle( 32, yPos, rowHeight, rowHeight );
Rectangle textBounds = new Rectangle( checkBoxBound.Right, yPos, Bounds.Width - (rowHeight * 2) - checkBoxBound.Right, rowHeight );
// Draw selection box.
Brush textColour = Brushes.Black;
if ( node.Selected )
{
graph.FillRectangle( Brushes.Blue, nodeBounds );
textColour = Brushes.Yellow;
}
// Draw node text.
graph.DrawString( node.Text, Font, textColour, textBounds );
// Draw Red/Green light
Image[] lightImages = new Image[] { CompleteLightImage, InCompleteLightImage };
Image lightImage = lightImages[node.Complete ? 1 : 0];
if ( lightImage != null )
{
graph.DrawImage( lightImage, lightBounds );
}
// Draw Spanner Icon
if ( SettingsImage != null )
{
graph.DrawImage( SettingsImage, spannerBounds );
}
// Draw check box.
VisualStyleRenderer renderer = null;
VisualStyleElement ve = node.Checked ? VisualStyleElement.Button.CheckBox.CheckedPressed : VisualStyleElement.Button.CheckBox.CheckedNormal;
if (VisualStyleRenderer.IsElementDefined( ve ))
{
renderer = new VisualStyleRenderer( ve );
}
if ( renderer != null )
{
renderer.DrawBackground( graph, checkBoxBound );
}
else
{
ControlPaint.DrawCheckBox( graph, checkBoxBound, node.Checked ? ButtonState.Checked : ButtonState.Normal );
}
yPos += Font.Height;
}
}
}
private NodeCollection mNodes = new NodeCollection();
[Category( "Behavior" )]
[Description( "Nodes" )]
[DesignerSerializationVisibility( DesignerSerializationVisibility.Content )]
[MergableProperty( false )]
[Bindable( false )]
public NodeCollection Nodes
{
get
{
return mNodes;
}
}
public Image CompleteLightImage { get; set; }
public Image InCompleteLightImage { get; set; }
public Image SettingsImage { get; set; }
}
我做了一些修改,因为我最初发布的一般与“DesignerSerializationVisibility”属性有关,这有帮助但我现在得到以下构建错误:
错误MSB3103:无效的Resx文件。无法加载类型App.Node,App, Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null,用于 .RESX文件。确保添加了必要的参考 到你的项目。
编辑2 :值得注意的是,只有当我在设计器中添加一堆节点时才出现我的问题,然后我得到上面的Resx错误。如果我从代码中手动添加节点,那么它就像我期望的那样工作......
答案 0 :(得分:21)
我相信您遇到此问题,因为Designer会自动尝试序列化所有公共UserControl属性。如果您的自定义UserControl设计时支持不需要此属性,则可以添加“DesignerSerializationVisibility”属性:
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
或者只是省略属性的get{}
和set{}
方法,并将其用作公共字段。
希望它有所帮助!
答案 1 :(得分:2)
这很奇怪。我已在我的笔记本地复制它,然后将Node类移动到另一个项目,它工作。我认为它是循环依赖的东西 - 它试图找到你的程序集(在我的情况下是WindowsFormsApplication1)构建,但它不能正在构建它现在。
希望能帮助你,我会尝试进一步挖掘。
<强>更新强> 另一种解决方法:从Node类中删除[Serialization]属性。在这种情况下,您将强制VS而不是在resx文件中生成节点内容,只需生成此类代码:
// Form1.designer.cs:
Node node1 = new Node();
node1.Checked = false;
node1.Complete = false;
node1.Selected = false;
node1.Text = null;
this.contr1.Nodes.Add(node1);