c# - UserControl 集合未标记为可序列化

标签 c# collections user-controls properties serializable

我一定是遗漏了一些非常明显的东西。我是 C# 的新手,但多年来一直使用 C/C++ 进行编程,如果有明显的问题,我深表歉意;)

[请参阅编辑以了解较新的问题]

我正在尝试创建一个包含 UserControl 的节点。我让 Control 出现在 WinForm 设计器中,我可以向它添加节点。但是,当我尝试运行代码时,出现以下错误:

Code generation for property 'Nodes' failed. Error was: 'Type App.Node' in Assembly 'App, version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.

然后我添加的节点都没有出现。

这开始让我发疯了,据我所知,它被标记为可序列化。

节点定义如下:

[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 评论的回应,这是我的用户控件:

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”属性相关的内容以来,我进行了一些修改,这对我有所帮助,但我现在遇到以下构建错误:

error MSB3103: Invalid Resx file. Could not load type App.Node, App, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null which is used in the .RESX file. Ensure that the necessary references have been added to your project.

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

最佳答案

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

[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 

或者简单地省略属性的 get{}set{} 方法并将其用作公共(public)字段。

希望对您有所帮助!

关于c# - UserControl 集合未标记为可序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9789066/

相关文章:

c# - 查找 IEnumerable 对象的类型

c# - .net core 3 equivalnet 配置添加 xml 序列化

c# - 使用 SQLITE/SQL COMPACT 数据库的跨平台 C# 应用程序

用于数据库支持集合的 Java 库

asp.net - 在页面加载时不加载用户控件的最佳方法是什么

c# - UserControl 元素由于其保护级别而无法访问

c# - 从另一个应用程序在一个应用程序的文本框中写入/读取文本

java - 集合框架的 HashMap.put(Entry k) 实现中 for 循环的目的是什么?

java - 找到给定时间范围内所有可能的时间组合

WPF - 哪个更好?风格还是用户控制?