UserControl集合未标记为可序列化

本文关键字:序列化 记为 集合 UserControl | 更新日期: 2023-09-27 18:28:35

我一定遗漏了一些非常明显的东西。我对C#很陌生,但多年来一直在用C/C++编程,如果这是显而易见的,我很抱歉;)

[有关新问题,请参阅编辑]

我正在尝试创建一个包含UserControl的节点。我有控件出现在WinForm设计器中,我可以向它添加节点。然而,当我尝试运行代码时,我会收到以下错误:

属性"Nodes"的代码生成失败。错误为:'类型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,用于.REX文件。确保添加了必要的参考资料您的项目。

编辑2:值得注意的是,只有当我在设计器中添加了一堆节点,然后出现上述Resx错误时,才会出现问题。如果我从代码中手动添加节点,那么一切都如我所期望的那样。。。

UserControl集合未标记为可序列化

我相信您有这个问题,因为Designer会自动尝试序列化所有公共UserControl属性。如果自定义UserControl设计时支持不需要此属性,则可以添加"DesignerSerializationVisibility"属性:

[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 

或者简单地省略该属性的CCD_ 1和CCD_。

希望它能有所帮助!

这很奇怪。我在笔记中本地复制了它,然后将Node类移到另一个项目中,它就工作了。我认为它是具有循环依赖性的东西——它试图找到你的程序集(在我的情况下,它是WindowsFormsApplication1),但它不能,因为它现在正在构建它。

希望对你有所帮助,我会努力进一步挖掘。

更新另一种解决方法是:从Node类中移除[Serialization]属性。在这种情况下,您将强制VS而不是在resx文件中生成Node内容,只需生成这样的代码:

// Form1.designer.cs:
Node node1 = new Node(); 
node1.Checked = false;
node1.Complete = false;
node1.Selected = false;
node1.Text = null;
this.contr1.Nodes.Add(node1);

我解决了这个问题,确保属性类有一个无参数构造函数。在将类序列化为没有无参数构造函数的文件时,我也遇到过类似的问题。

    [Serializable]
    public class ChartTitle {
        public Color BackColor { get; set; }
        public string Text { get; set; }
        public ChartTitle() {   // <--- Make sure have parameterless constructor
            BackColor = SystemColors.Control;
            Text = String.Empty;
        }
    }