【问题标题】:C# Winforms - Force write a property value of a user control to resx fileC# Winforms - 强制将用户控件的属性值写入 resx 文件
【发布时间】:2017-08-29 08:46:27
【问题描述】:

我有一个具有byte[] 属性的用户控件。阵列在设计时也会变得巨大。当 Visual Studio 保存表单时,它会使用此方法将其保存到 cs 文件中

this.ctlShowSpreadsheet1.SerializationContent = new byte[] {
        ((byte)(80)),
        ((byte)(75)),
        ((byte)(3)),
        ((byte)(4)),
        ((byte)(20)),
        ((byte)(0)),
        ((byte)(2)),
        ((byte)(0)),
        ((byte)(8)),
        ((byte)(0)),
        ((byte)(128)),
        ((byte)(84)),
        ((byte)(29)),
        ...

有没有办法强制将字节数组保存到 resx 文件中? 我尝试更改 DesignerSerializationVisibility 但没有结果。

【问题讨论】:

  • 你可以,但它没有帮助。您可以将[Localizable(true)] 添加到属性并将表单的Localizable 属性更改为true。然后它将实际数据放入resx 文件中,但随后它将对每个元素的引用添加到designer.cs 文件中。
  • 你试过LocalizableAttribute并设置Localizable
  • @MatthewWatson 我不能确定UserControl 用户在表单上设置了Localizable = true。我无法理解然后它会将实际数据放入resx 文件中,但它会在designer.cs 文件中添加对每个元素的引用。 VS 是否会为 resx 中的每个元素设置一个数组元素(与之前完全一样,但从 resx 中读取每个字节?) resx 不能存储一个数组,而 VS 在单个语句中读取并设置整个数组吗?
  • 我的意思是,虽然它将数据放入 .resx 文件,但 Designer.cs 文件包含类似 (byte)(resources.GetObject("testUserControl1.Data"))), 的行,用于数组的每个元素。这似乎更糟!
  • 嗯,不得不编辑这个属性听起来很不切实际。不是 [Localizable],它需要底层属性类型的 [Serializable] 属性来说服设计者该类型的对象可以写入 .resx 文件。怎么用 byte[] 来存储电子表格(?)是非常模糊的。 MemoryStream 是可序列化的。

标签: c# .net winforms windows-forms-designer


【解决方案1】:

如果属性的类型为Serializable 类型,则设计器将其序列化到资源文件中。

因此,在您的情况下,您可以创建一个可序列化的字节列表并使用它来存储您的字节列表。请记住,设计者需要您的可序列化类位于不同的程序集中。

示例

在下面的示例中,我创建了一个具有字节列表属性的控件,该属性将存储在表单的 resx 文件中。为此,请按以下步骤操作:

  1. 创建一个Windows Forms项目的新项目作为您的主项目。
  2. Windows 窗体控件库 的新项目添加到解决方案中。
  3. 将包含以下代码的 c# 文件添加到控件库项目中。
  4. 将控件库项目的引用添加到主 Windows 窗体项目。
  5. 构建解决方案。
  6. 在您的表单上删除MyControl 的实例。
  7. 然后在属性网格中找到ByteList属性并展开它。
  8. 编辑Bytes 属性。
  9. 保存表单
  10. 查看属性值保存在表单的资源文件中。设计师还生成代码以从资源中获取价值:

    this.myControl1.ByteList = ((WindowsFormsControlLibrary1.SerializableByteList)
        (resources.GetObject("myControl1.ByteList")));
    

代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
public class MyControl: UserControl
{
    public MyControl()
    {
        ByteList = new SerializableByteList();
    }
    [TypeConverter(typeof(ExpandableObjectConverter))]
    public SerializableByteList ByteList { get; set; }
}

[Serializable]
public class SerializableByteList
{
    public SerializableByteList()
    {
        Bytes = new List<byte>();
    }
    public List<byte> Bytes { get; set; }
}

注意

有关设计器序列化的更多信息,请查看Customizing Code Generation in the .NET Framework Visual Designers

使用二进制序列化

并非所有类型都适合代码生成。例如,如何将位图序列化为代码?你可以编码 它作为一个字符串,但对于一个中等大小的位图,字符串 可能比文件中的其余代码大得多。这 Designer 通过将二进制类型持久化到 将值推送到 .NET 清单的资源文件 框架应用。然后,当应用程序初始化时,它 可以将值从程序集的清单中加载回来。

代码生成器在尝试序列化类型时遵循以下顺序:

  • 内置原始类型(字符串、布尔值、整数、浮点数等)的序列化
  • 自定义类型的InstanceDescriptor序列化
  • 标记为可序列化的类型的二进制序列化。

请记住,您可以控制设计器序列化 通过为您的类实现ISerializable 接口来创建对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多