Коллекция UserControl не помечена как сериализуемая - PullRequest
9 голосов
/ 20 марта 2012

Я, должно быть, упускаю что-то действительно очевидное. Я довольно новичок в C #, но программирую на C / C ++ в течение многих лет, так что извините, если это что-то ослепительно очевидно;)

[См. Редактировать для новых проблем]

Я пытаюсь создать узел, содержащий UserControl. У меня есть элемент управления, появляющийся в конструкторе WinForm, и я могу добавить к нему узлы. Однако, когда я пытаюсь запустить код, я получаю следующую ошибку:

Ошибка генерации кода для свойства 'Nodes'. Ошибка была: «Тип App.Node 'in Assembly' App, версия = 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()
    {
    }
};

Как у коллекции, так и у самого узла установлен атрибут «Сериализуемый», как вы можете видеть.

Свойство 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, Версия = 1.0.0.0, Культура = нейтральная, PublicKeyToken = null, которая используется в файл .RESX. Убедитесь, что необходимые ссылки были добавлены к вашему проекту.

Редактировать 2 : Стоит отметить, что мои проблемы возникают только тогда, когда я добавляю несколько узлов в конструктор, тогда я получаю вышеуказанную ошибку Resx. Если я добавлю узлы вручную из кода, тогда все будет работать так, как я ожидал ...

Ответы [ 2 ]

21 голосов
/ 26 июня 2012

Я считаю, что у вас есть эта проблема, потому что Designer автоматически пытается сериализовать все общедоступные свойства UserControl.Если это свойство не требуется для вашей пользовательской поддержки времени разработки UserControl, вы можете добавить атрибут «DesignerSerializationVisibility»:

[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 

или просто пропустить методы свойства get{} и set{} и использовать егокак открытое поле.

Надеюсь, это поможет!

2 голосов
/ 20 марта 2012

Это очень странно. Я воспроизвел это локально в своей заметке, затем переместил класс Node в другой проект, и это сработало. Я думаю, что это что-то с циклическими зависимостями - оно пытается найти вашу сборку (в моем случае это была WindowsFormsApplication1), но не может, поскольку строит ее прямо сейчас.

Надеюсь, что это поможет вам, и я постараюсь копать дальше.

Обновление Другой способ решить эту проблему: удалить атрибут [Serialization] из класса Node. В этом случае вы будете принудительно создавать 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...