演练:序列化标准类型集合

自定义控件有时会将集合作为属性公开。 此演练演示如何使用 DesignerSerializationVisibilityAttribute 类来控制集合在设计时的序列化方式。 将 Content 值应用于集合属性可确保该属性将被序列化。

注意

本文专为 .NET Framework 而撰写。 如果使用 .NET 6 或更高版本,请谨慎使用此内容。 设计器系统已针对 Windows 窗体进行更改,因此请务必查看自 .NET Framework 以来对设计器所做的更改一文。

要将本主题中的代码作为单个列表进行复制,请参阅如何:使用 DesignerSerializationVisibilityAttribute 序列化标准类型的集合

先决条件

若要完成本演练,必须具有 Visual Studio。

创建具有可序列化集合的控件

第一步是创建具有可序列化集合作为属性的控件。 可以使用集合编辑器编辑此集合的内容,该编辑器可从“属性”窗口访问

  1. 在 Visual Studio 中,创建一个 Windows 控件库项目,并将其命名为 SerializationDemoControlLib

  2. UserControl1 重命名为 SerializationDemoControl。 有关更多信息,请参阅重命名代码符号重构

  3. 在“属性”窗口中,将 Padding.All 属性的值设置为“10”

  4. SerializationDemoControl 中放置一个 TextBox 控件。

  5. 选择 TextBox 控件。 在“属性”窗口中,设置下列属性

    properties 更改为
    多行 true
    靠接 Fill
    ScrollBars Vertical
    ReadOnly true
  6. 在代码编辑器中,在 SerializationDemoControl 中声明一个名为 stringsValue 的字符串数组字段

        // This field backs the Strings property.
    private:
        array<String^>^ stringsValue;
    
    
    
    // This field backs the Strings property.
    private String[] stringsValue = new String[1];
    
    ' This field backs the Strings property.
     Private stringsValue(1) As String
    
  7. SerializationDemoControl 上定义 Strings 属性。

    注意

    Content 值用于启用集合的序列化。

        // When the DesignerSerializationVisibility attribute has
        // a value of "Content" or "Visible" the designer will 
        // serialize the property. This property can also be edited 
        // at design time with a CollectionEditor.
    public:
        [DesignerSerializationVisibility(
            DesignerSerializationVisibility::Content)]
        property array<String^>^ Strings
        {
            array<String^>^ get()
            {
                return this->stringsValue;
            }
            void set(array<String^>^ value)
            {
                this->stringsValue = value;
    
                // Populate the contained TextBox with the values
                // in the stringsValue array.
                StringBuilder^ sb =
                    gcnew StringBuilder(this->stringsValue->Length);
    
                for (int i = 0; i < this->stringsValue->Length; i++)
                {
                    sb->Append(this->stringsValue[i]);
                    sb->Append(Environment::NewLine);
                }
    
                this->demoControlTextBox->Text = sb->ToString();
            }
        }
    
    // When the DesignerSerializationVisibility attribute has
    // a value of "Content" or "Visible" the designer will
    // serialize the property. This property can also be edited
    // at design time with a CollectionEditor.
    [DesignerSerializationVisibility(
        DesignerSerializationVisibility.Content )]
    public String[] Strings
    {
        get
        {
            return this.stringsValue;
        }
        set
        {
            this.stringsValue = value;
    
            // Populate the contained TextBox with the values
            // in the stringsValue array.
            StringBuilder sb =
                new StringBuilder(this.stringsValue.Length);
    
            for (int i = 0; i < this.stringsValue.Length; i++)
            {
                sb.Append(this.stringsValue[i]);
                sb.Append("\r\n");
            }
    
            this.textBox1.Text = sb.ToString();
        }
    }
    
    ' When the DesignerSerializationVisibility attribute has
    ' a value of "Content" or "Visible" the designer will 
    ' serialize the property. This property can also be edited 
    ' at design time with a CollectionEditor.
     <DesignerSerializationVisibility( _
         DesignerSerializationVisibility.Content)> _
     Public Property Strings() As String()
         Get
             Return Me.stringsValue
         End Get
         Set(ByVal value As String())
             Me.stringsValue = Value
    
             ' Populate the contained TextBox with the values
             ' in the stringsValue array.
             Dim sb As New StringBuilder(Me.stringsValue.Length)
    
             Dim i As Integer
             For i = 0 To (Me.stringsValue.Length) - 1
                 sb.Append(Me.stringsValue(i))
                 sb.Append(ControlChars.Cr + ControlChars.Lf)
             Next i
    
             Me.textBox1.Text = sb.ToString()
         End Set
     End Property
    
  8. 按 F5 生成项目并在“UserControl 测试容器”中运行该控件

  9. 在 UserControl 测试容器的 PropertyGrid 中找到“字符串”属性。 选择 Strings 属性,然后选择省略号 (The Ellipsis button (...) in the Properties window of Visual Studio) 按钮以打开“字符串集合编辑器”

  10. 在字符串集合编辑器中输入多个字符串。 在每个字符串末尾按 Enter 键将其隔开。 输入完字符串后单击“确定”

注意

所键入的字符串随即显示在 SerializationDemoControlTextBox 中。

序列化集合属性

若要测试控件的序列化行为,需要将该控件置于一个窗体上并使用集合编辑器更改集合的内容。 可以通过查看 Windows 窗体设计器向其中发出代码的特殊设计器文件来查看序列化集合状态

  1. 向该解决方案添加一个“Windows 应用程序”项目。 将项目命名为 SerializationDemoControlTest

  2. 在工具箱中,找到名为 SerializationDemoControlLib 组件的选项卡。 在此选项卡中,你将找到 SerializationDemoControl。 有关详细信息,请参阅演练:使用自定义组件自动填充工具箱

  3. 在窗体上放置一个 SerializationDemoControl

  4. 在属性窗口中找到 Strings 属性。 单击 Strings 属性,然后单击省略号 (The Ellipsis button (...) in the Properties window of Visual Studio.) 按钮以打开“字符串集合编辑器”

  5. 在字符串集合编辑器中键入多个字符串。 在每个字符串末尾按 Enter 将其隔开。 输入完字符串后单击“确定”

    注意

    所键入的字符串随即显示在 SerializationDemoControlTextBox 中。

  6. 在“解决方案资源管理器”中,单击“显示所有文件”按钮。

  7. 打开 Form1 节点。 其下方有一个名为 Form1.Designer.cs 或 Form1.Designer.vb 的文件。 这是 Windows 窗体设计器向其中发出代码的文件,该代码表示窗体及其子控件的设计时状态。 在“代码编辑器”中打开此文件。

  8. 打开名为“Windows 窗体设计器生成的代码”的区域,找到标有 serializationDemoControl1 的部分。 此标签下方是表示控件的序列化状态的代码。 在步骤 5 中键入的字符串随即显示在 Strings 属性的赋值中。 以下 C# 和 Visual Basic 中的代码示例显示的代码类似于你在键入字符串“red”、“orange”和“yellow”时所看到的代码。

    this.serializationDemoControl1.Strings = new string[] {
            "red",
            "orange",
            "yellow"};
    
    Me.serializationDemoControl1.Strings = New String() {"red", "orange", "yellow"}
    
  9. 在代码编辑器中,将 Strings 属性上的 DesignerSerializationVisibilityAttribute 的值更改为 Hidden

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    
    <DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
    
  10. 重新生成解决方案并重复步骤 3 和 4。

注意

在这种情况下,Windows 窗体设计器不会向 Strings 属性发出任何赋值

后续步骤

了解如何序列化标准类型的集合后,请考虑将自定义控件更深入地集成到设计时环境中。 以下主题介绍如何增强自定义控件的设计时集成:

另请参阅