2012-03-20 23 views
7

Tôi phải thiếu một cái gì đó thực sự rõ ràng. Tôi khá mới để C# nhưng đã được lập trình trong C/C++ trong nhiều năm, vì vậy xin lỗi nếu nó là một cái gì đó hiển nhiên;)Bộ sưu tập UserControl không được đánh dấu là serializable

[Xem Chỉnh sửa cho các vấn đề mới]

Tôi đang cố gắng để tạo một nút chứa UserControl. Tôi có Control xuất hiện trong trình thiết kế WinForm và tôi có thể thêm các nút vào nó. Tuy nhiên, khi tôi thử và chạy mã, tôi nhận được lỗi sau:

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.

và sau đó không có nút nào tôi thêm vào hiển thị.

Điều này đang bắt đầu khiến tôi phát điên, theo như tôi thấy, nó được đánh dấu là có thể tuần tự hóa.

Các nút được xác định như sau:

[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; } 
}; 

sau đó tôi xác định một "Bộ sưu tập" như sau:

[Serializable] 
public class NodeCollection : List<Node> 
{ 
    public NodeCollection() : 
     base() 
    { 
    } 
}; 

Cả hai bộ sưu tập và nút tự có "Serializable" thuộc tính thiết lập như bạn có thể thấy.

Khách sạn Nodes đề cập trong các lỗi được định nghĩa như sau

private NodeCollection  mNodes = new NodeCollection(); 

    [Category("Behavior")] 
    [Description("Nodes")] 
    public NodeCollection Nodes 
    { 
     get 
     { 
      return mNodes; 
     } 
    } 

Vì vậy, có ai bị bất kỳ ý tưởng whats tôi đang làm sai ở đây?

Edit: Đáp lại ý kiến ​​Archeg của này là UserControl của tôi:

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; } 
} 

Tôi đã thực hiện một số thay đổi kể từ khi tôi ban đầu được đăng thường liên quan đến việc "DesignerSerializationVisibility" thuộc tính đó đã giúp nhưng bây giờ tôi nhận lỗi build sau:

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.

chỉnh sửa 2: nó đáng chú ý là vấn đề của tôi chỉ xảy ra khi tôi thêm một loạt các N odes trong nhà thiết kế sau đó tôi nhận được lỗi Resx ở trên. Nếu tôi thêm các nút theo cách thủ công từ mã thì tất cả đều hoạt động như tôi mong đợi ...

+0

Bạn sử dụng điều khiển nào? Nó có tùy chỉnh không? – Archeg

+0

@Archeg: Yup hoàn toàn tùy chỉnh bắt nguồn trực tiếp từ UserControl – Goz

+0

Bạn có thể đăng mã UserControl của mình không? – Archeg

Trả lời

18

Tôi tin rằng bạn có vấn đề này vì thiết kế tự động cố gắng serialize tất cả các thuộc tính UserControl công cộng.Nếu thuộc tính này là không cần thiết cho tùy chỉnh UserControl hỗ trợ thời gian thiết kế của bạn, sau đó bạn có thể Add "DesignerSerializationVisibility" thuộc tính:

[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 

hoặc đơn giản là bỏ qua get{}set{} phương pháp của tài sản và sử dụng nó như là một lĩnh vực công cộng.

Hy vọng điều đó sẽ hữu ích!

+1

Giải pháp chính xác của nó. Bạn đã cứu tôi. –

2

Điều đó rất lạ. Tôi đã sao chép nó cục bộ trên ghi chú của tôi, sau đó chuyển lớp Node sang một dự án khác và nó đã hoạt động. Tôi nghĩ rằng nó là một cái gì đó với phụ thuộc vòng tròn - nó cố gắng tìm lắp ráp của bạn (trong trường hợp của tôi nó đã được WindowsFormsApplication1) được xây dựng, nhưng nó không thể vì nó được xây dựng nó ngay bây giờ.

Hy vọng sẽ giúp bạn và tôi sẽ cố gắng đào sâu hơn nữa.

Cập nhật Một cách khác để giải quyết: loại bỏ thuộc tính [Nối tiếp] khỏi lớp Nút. Trong trường hợp đó bạn sẽ buộc VS thay vì tạo ra nội dung Node trong file resx, chỉ cần tạo mã ví dụ:

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

Đã thêm một giải pháp khác cho sự cố – Archeg

+0

Đã thêm một chỉnh sửa bổ sung ở dưới cùng. Về cơ bản vấn đề nằm với một cái gì đó đi sai với các nhà thiết kế ... dunno nếu điều đó giúp bạn ở tất cả – Goz

+0

Vâng, có vẻ như VS không tạo ra dữ liệu tuần tự trên điều khiển nó được xây dựng. Bạn có phiền nếu tôi đăng bài đó như một lỗi cho Microsoft, vì tôi đã không thể tìm thấy một số lời giải thích có ý nghĩa? – Archeg

Các vấn đề liên quan