如何创建结构列表类型的应用程序设置参数?
How to create an application settings parameter of type a list of structs?
在我的项目中,我有一个自定义结构:
struct Point {
public uint xPoint { get; }
public uint yPoint { get; }
public Point(uint x, uint y) {
xPoint = x;
yPoint = y;
}
}
我正在使用这些点的列表:
List<Point> pathToNavigate = new List<Point>();
我想做的是将我的积分列表保存到 Settings.settings:
我不知道如何将字符串更改为我的结构点列表。
我尝试弄乱 xml 并手动添加我的选项,但我不知道该怎么做。我发现的大多数东西都告诉我使用自定义命名空间,但我也无法使用我的 Point 结构列表。
编辑:我的问题是使用列表的自定义结构。问题不是将项目添加到列表,而是能够正确加载它们的内容。
将副本应用于您的案例(我无法标记它,因为我无法重新投票结束,我 post 这个答案是为了解决您的困难,同时更精确和更完整比各种教程和重复):
How to save a List<string> on Settings.Default?
在例如下面的命名空间中具有可序列化结构:
namespace WindowsFormsAppTest
{
[Serializable]
public struct Point
{
public uint xPoint { get; set; }
public uint yPoint { get; set; }
public Point(uint x, uint y)
{
xPoint = x;
yPoint = y;
}
}
}
如前所述,属性必须是可读写的,所以我添加了自动设置器,并且结构必须通过添加属性可序列化。
编译项目。
您需要创建一个字符串参数,例如名称为 MyList
:
然后使用任何文本编辑器手动编辑 Settings.settings
,将其类型更改为:
System.Collections.Generic<WindowsFormsAppTest.Point>
在 HTML 中的文本编码如:
System.Collections.Generic.List<WindowsFormsAppTest.Point>
Settings.settings
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="WindowsFormsAppTest.Properties" GeneratedClassName="Settings">
<Profiles />
<Settings>
<Setting Name="MyList" Type="System.Collections.Generic.List<WindowsFormsAppTest.Point>" Scope="User">
<Value Profile="(Default)" />
</Setting>
</Settings>
</SettingsFile>
保存后,去Visual Studio重新加载文件,然后你就能看到类型改变了:
您需要使用设计器更新此设置生成的 C# 代码文件,方法是展开参数类型并单击此自定义列表类型:
如果没有,或者出现问题,您需要手动更新这些文件:
app.config to serializeAs Xml
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="WindowsFormsAppTest.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/></startup>
<userSettings>
<WindowsFormsAppTest.Properties.Settings>
<setting name="MyList" serializeAs="Xml">
<value />
</setting>
</WindowsFormsAppTest.Properties.Settings>
</userSettings>
</configuration>
Settings.Designer.cs to change the type of the property
public global::System.Collections.Generic.List<WindowsFormsAppTest.Point> MyList {
get {
return ((global::System.Collections.Generic.List<WindowsFormsAppTest.Point>)(this["MyList"]));
}
全部保存and/or重新编译
现在,您可以在 Main
方法或主窗体的构造函数或加载事件处理程序中编写例如:
private void FormTest_Load(object sender, EventArgs e)
{
if ( Properties.Settings.Default.MyList == null )
Properties.Settings.Default.MyList = new List<Point>();
Properties.Settings.Default.Save();
}
例如在按钮单击事件处理程序中:
private void ButtonCreate_Click(object sender, EventArgs e)
{
Properties.Settings.Default.MyList.Add(new Point(10, 10));
Properties.Settings.Default.MyList.Add(new Point(10, 20));
Properties.Settings.Default.MyList.Add(new Point(20, 20));
Properties.Settings.Default.MyList.Add(new Point(50, 50));
Properties.Settings.Default.Save();
}
现在的配置文件是:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<userSettings>
<WindowsFormsAppTest.Properties.Settings>
<setting name="MyList" serializeAs="Xml">
<value>
<ArrayOfPoint xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Point>
<xPoint>10</xPoint>
<yPoint>10</yPoint>
</Point>
<Point>
<xPoint>10</xPoint>
<yPoint>20</yPoint>
</Point>
<Point>
<xPoint>20</xPoint>
<yPoint>20</yPoint>
</Point>
<Point>
<xPoint>50</xPoint>
<yPoint>50</yPoint>
</Point>
</ArrayOfPoint>
</value>
</setting>
</WindowsFormsAppTest.Properties.Settings>
</userSettings>
</configuration>
要更改一个项目,我们可以编写,因为是结构所以是值类型:
private void ButtonUpdate_Click(object sender, EventArgs e)
{
var point = Properties.Settings.Default.MyList[0];
point.xPoint = 100;
point.yPoint = 100;
Properties.Settings.Default.MyList[0] = point;
Properties.Settings.Default.Save();
}
现在设置文件有:
<Point>
<xPoint>100</xPoint>
<yPoint>100</yPoint>
</Point>
...
要对此进行测试,我们可以使用另一个按钮列出项目:
private void ButtonShow_Click(object sender, EventArgs e)
{
var list = Properties.Settings.Default.MyList.Select(p => $"{p.xPoint}, {p.yPoint}");
MessageBox.Show(string.Join(Environment.NewLine, list.ToArray()));
}
备注
要清理应用程序设置,您需要删除例如所有这些文件夹:
c:\Users\User\AppData\Local\Organization\WindowsFormsAppTest.exe_Url_*
其中 Organization
和 WindowsFormsAppTest
来自 AssemblyInfo.cs
中使用字段 AssemblyCompany
和 AssemblyTitle
.
定义的清单文件
以下步骤有效。
但是,我认为您的问题仅仅是因为 xPoint
和 yPoint
没有 public setter。这是由于 XmlSerializer
作品。请参阅文档 here。
首先,创建一个设置。在这种情况下,我将其命名为 ListOfPoints
。类型无关紧要,我们还是要更改它。
手动编辑“Settings.settings”。我只是用 Visual Studio 的 XML 编辑器打开它,但使用你喜欢的。
然后仅更改设置的类型。请注意,您需要对 <
和 >
.
使用 HTML 编码
整个Settings.settings:
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="WindowsFormsApp1.Properties" GeneratedClassName="Settings">
<Profiles />
<Settings>
<Setting Name="ListOfPoints" Type="System.Collections.Generic.List<WindowsFormsApp1.MyPoint>" Scope="User">
<Value Profile="(Default)" />
</Setting>
</Settings>
</SettingsFile>
唯一的改变是:
Type="System.Collections.Generic.List<WindowsFormsApp1.MyPoint>"
所有代码:
[Serializable]
public struct MyPoint
{
public uint X { get; set; }
public uint Y { get; set; }
public MyPoint(uint x, uint y)
{
X = x;
Y = y;
}
public override bool Equals(object obj)
{
if (!(obj is MyPoint))
return false;
var other = (MyPoint)obj;
return other.X == X && other.Y == Y;
}
public override int GetHashCode()
{
return unchecked(X.GetHashCode() ^ Y.GetHashCode());
}
}
private static readonly List<MyPoint> saveMe = new List<MyPoint>();
private static List<MyPoint> loadMe;
private static void SaveData()
{
Properties.Settings.Default.ListOfPoints = saveMe;
Properties.Settings.Default.Save();
}
private static void LoadData()
{
Properties.Settings.Default.Reload();
loadMe = Properties.Settings.Default.ListOfPoints;
TestData();
}
private static void TestData()
{
if (loadMe.Count != saveMe.Count)
throw new Exception("Different counts");
for (int i = 0; i < loadMe.Count; i++)
{
if (!loadMe[i].Equals(saveMe[i]))
throw new Exception($"{nameof(MyPoint)} at index {i} doesn't match");
}
}
通过向 saveMe
添加您想要的任何内容来对此进行测试。然后是 运行 SaveData
然后是 LoadData
.
LoadData
如果数据不匹配会抛出异常。
在我的项目中,我有一个自定义结构:
struct Point {
public uint xPoint { get; }
public uint yPoint { get; }
public Point(uint x, uint y) {
xPoint = x;
yPoint = y;
}
}
我正在使用这些点的列表:
List<Point> pathToNavigate = new List<Point>();
我想做的是将我的积分列表保存到 Settings.settings:
我不知道如何将字符串更改为我的结构点列表。
我尝试弄乱 xml 并手动添加我的选项,但我不知道该怎么做。我发现的大多数东西都告诉我使用自定义命名空间,但我也无法使用我的 Point 结构列表。
编辑:我的问题是使用列表的自定义结构。问题不是将项目添加到列表,而是能够正确加载它们的内容。
将副本应用于您的案例(我无法标记它,因为我无法重新投票结束,我 post 这个答案是为了解决您的困难,同时更精确和更完整比各种教程和重复):
How to save a List<string> on Settings.Default?
在例如下面的命名空间中具有可序列化结构:
namespace WindowsFormsAppTest
{
[Serializable]
public struct Point
{
public uint xPoint { get; set; }
public uint yPoint { get; set; }
public Point(uint x, uint y)
{
xPoint = x;
yPoint = y;
}
}
}
如前所述,属性必须是可读写的,所以我添加了自动设置器,并且结构必须通过添加属性可序列化。
编译项目。
您需要创建一个字符串参数,例如名称为 MyList
:
然后使用任何文本编辑器手动编辑 Settings.settings
,将其类型更改为:
System.Collections.Generic<WindowsFormsAppTest.Point>
在 HTML 中的文本编码如:
System.Collections.Generic.List<WindowsFormsAppTest.Point>
Settings.settings
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="WindowsFormsAppTest.Properties" GeneratedClassName="Settings">
<Profiles />
<Settings>
<Setting Name="MyList" Type="System.Collections.Generic.List<WindowsFormsAppTest.Point>" Scope="User">
<Value Profile="(Default)" />
</Setting>
</Settings>
</SettingsFile>
保存后,去Visual Studio重新加载文件,然后你就能看到类型改变了:
您需要使用设计器更新此设置生成的 C# 代码文件,方法是展开参数类型并单击此自定义列表类型:
如果没有,或者出现问题,您需要手动更新这些文件:
app.config to serializeAs Xml
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="WindowsFormsAppTest.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/></startup>
<userSettings>
<WindowsFormsAppTest.Properties.Settings>
<setting name="MyList" serializeAs="Xml">
<value />
</setting>
</WindowsFormsAppTest.Properties.Settings>
</userSettings>
</configuration>
Settings.Designer.cs to change the type of the property
public global::System.Collections.Generic.List<WindowsFormsAppTest.Point> MyList {
get {
return ((global::System.Collections.Generic.List<WindowsFormsAppTest.Point>)(this["MyList"]));
}
全部保存and/or重新编译
现在,您可以在 Main
方法或主窗体的构造函数或加载事件处理程序中编写例如:
private void FormTest_Load(object sender, EventArgs e)
{
if ( Properties.Settings.Default.MyList == null )
Properties.Settings.Default.MyList = new List<Point>();
Properties.Settings.Default.Save();
}
例如在按钮单击事件处理程序中:
private void ButtonCreate_Click(object sender, EventArgs e)
{
Properties.Settings.Default.MyList.Add(new Point(10, 10));
Properties.Settings.Default.MyList.Add(new Point(10, 20));
Properties.Settings.Default.MyList.Add(new Point(20, 20));
Properties.Settings.Default.MyList.Add(new Point(50, 50));
Properties.Settings.Default.Save();
}
现在的配置文件是:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<userSettings>
<WindowsFormsAppTest.Properties.Settings>
<setting name="MyList" serializeAs="Xml">
<value>
<ArrayOfPoint xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Point>
<xPoint>10</xPoint>
<yPoint>10</yPoint>
</Point>
<Point>
<xPoint>10</xPoint>
<yPoint>20</yPoint>
</Point>
<Point>
<xPoint>20</xPoint>
<yPoint>20</yPoint>
</Point>
<Point>
<xPoint>50</xPoint>
<yPoint>50</yPoint>
</Point>
</ArrayOfPoint>
</value>
</setting>
</WindowsFormsAppTest.Properties.Settings>
</userSettings>
</configuration>
要更改一个项目,我们可以编写,因为是结构所以是值类型:
private void ButtonUpdate_Click(object sender, EventArgs e)
{
var point = Properties.Settings.Default.MyList[0];
point.xPoint = 100;
point.yPoint = 100;
Properties.Settings.Default.MyList[0] = point;
Properties.Settings.Default.Save();
}
现在设置文件有:
<Point>
<xPoint>100</xPoint>
<yPoint>100</yPoint>
</Point>
...
要对此进行测试,我们可以使用另一个按钮列出项目:
private void ButtonShow_Click(object sender, EventArgs e)
{
var list = Properties.Settings.Default.MyList.Select(p => $"{p.xPoint}, {p.yPoint}");
MessageBox.Show(string.Join(Environment.NewLine, list.ToArray()));
}
备注
要清理应用程序设置,您需要删除例如所有这些文件夹:
c:\Users\User\AppData\Local\Organization\WindowsFormsAppTest.exe_Url_*
其中 Organization
和 WindowsFormsAppTest
来自 AssemblyInfo.cs
中使用字段 AssemblyCompany
和 AssemblyTitle
.
以下步骤有效。
但是,我认为您的问题仅仅是因为 xPoint
和 yPoint
没有 public setter。这是由于 XmlSerializer
作品。请参阅文档 here。
首先,创建一个设置。在这种情况下,我将其命名为 ListOfPoints
。类型无关紧要,我们还是要更改它。
手动编辑“Settings.settings”。我只是用 Visual Studio 的 XML 编辑器打开它,但使用你喜欢的。
然后仅更改设置的类型。请注意,您需要对 <
和 >
.
整个Settings.settings:
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="WindowsFormsApp1.Properties" GeneratedClassName="Settings">
<Profiles />
<Settings>
<Setting Name="ListOfPoints" Type="System.Collections.Generic.List<WindowsFormsApp1.MyPoint>" Scope="User">
<Value Profile="(Default)" />
</Setting>
</Settings>
</SettingsFile>
唯一的改变是:
Type="System.Collections.Generic.List<WindowsFormsApp1.MyPoint>"
所有代码:
[Serializable]
public struct MyPoint
{
public uint X { get; set; }
public uint Y { get; set; }
public MyPoint(uint x, uint y)
{
X = x;
Y = y;
}
public override bool Equals(object obj)
{
if (!(obj is MyPoint))
return false;
var other = (MyPoint)obj;
return other.X == X && other.Y == Y;
}
public override int GetHashCode()
{
return unchecked(X.GetHashCode() ^ Y.GetHashCode());
}
}
private static readonly List<MyPoint> saveMe = new List<MyPoint>();
private static List<MyPoint> loadMe;
private static void SaveData()
{
Properties.Settings.Default.ListOfPoints = saveMe;
Properties.Settings.Default.Save();
}
private static void LoadData()
{
Properties.Settings.Default.Reload();
loadMe = Properties.Settings.Default.ListOfPoints;
TestData();
}
private static void TestData()
{
if (loadMe.Count != saveMe.Count)
throw new Exception("Different counts");
for (int i = 0; i < loadMe.Count; i++)
{
if (!loadMe[i].Equals(saveMe[i]))
throw new Exception($"{nameof(MyPoint)} at index {i} doesn't match");
}
}
通过向 saveMe
添加您想要的任何内容来对此进行测试。然后是 运行 SaveData
然后是 LoadData
.
LoadData
如果数据不匹配会抛出异常。