C#: 在运行时创建新的设置

24

c# Windows Forms:如何在运行时创建新的设置,以便它们永久保存为Settings.Default - 值?

8个回答

20

如果仍然有人关心,可以通过Settings.Default.Properties.Add(...)动态添加设置,并在保存后将这些设置持久化到本地存储中(我发现这些条目被反映在漫游文件中)。

不过,在重新加载后,动态添加的设置似乎会在Settings.Default.Properties集合中丢失。

我可以通过在首次访问前添加动态属性来解决此问题。 例如(请注意,我从基本设置“创建”了我的动态设置):

// create new setting from a base setting:
var property = new SettingsProperty(Settings.Default.Properties["<baseSetting>"]);
property.Name = "<dynamicSettingName>";
Settings.Default.Properties.Add(property);
// will have the stored value:
var dynamicSetting = Settings.Default["<dynamicSettingName>"];

我不知道 Microsoft 是否支持此功能,因为关于这个主题的文档非常少。

问题在此处也有描述:http://www.vbdotnetforums.com/vb-net-general-discussion/29805-my-settings-run-time-added-properties-dont-save.html#post88152,提供了一些解决方案:http://msdn.microsoft.com/en-us/library/saa62613(v=VS.100).aspx(请参见社区内容 - 标题为“如何创建 / 保存 / 加载动态(运行时)设置”)。但这是 VB.NET。


这很棒,但你能帮我吗:我该如何设置属性类型?非常感谢。 - amr osama
5
如何设置属性类型?property.PropertyType = typeof(YourObject);要设置属性类型,可以使用上述代码,并将"YourObject"替换为所需的类型名称。 - Jesse Chisholm
1
此外,在此处也有描述。但是,在添加属性后,它调用了Properties.Settings.Default.Save();不确定是否需要,因为 John 的答案中没有提到。 - Ruben9922

15

除了John的保存解决方案外,正确的加载方法是添加属性,然后在设置中执行Reload()。

您的动态设置将保留下来!

对于完整的示例,在库代码中使用有效,因为您可以传递设置..

ApplicationSettingsBase settings = passed_in;
SettingsProvider sp = settings.Providers["LocalFileSettingsProvider"];
SettingsProperty p = new SettingsProperty("your_prop_name");
your_class conf = null;
p.PropertyType = typeof( your_class );
p.Attributes.Add(typeof(UserScopedSettingAttribute),new UserScopedSettingAttribute());
p.Provider = sp;
p.SerializeAs = SettingsSerializeAs.Xml;
SettingsPropertyValue v = new SettingsPropertyValue( p );
settings.Properties.Add( p );

settings.Reload();
conf = (your_class)settings["your_prop_name"];
if( conf == null )
{
   settings["your_prop_name"] = conf = new your_class();
   settings.Save();
}

你在 Properties.Add 行上面声明 'v' 时有没有漏掉什么操作? - bc3tech
错过的东西:v.PropertyValue = your_value; - Jesse Chisholm
我认为没有必要创建一个新的SettingsPropertyValue - 这一行可以省略。这就是为什么@Drew的代码能够工作,尽管不如它本应该的那样高效 :-) - JonP

8

由于Settings类是在构建时生成的(或者说,每当您从设计师中更新设置文件时),因此您无法将此机制用于动态场景。但是,您可以向应用程序设置添加一些集合或字典,并在运行时动态修改它们。


虽然说“它不符合范式”是正确的说法,但说“你不能”并不完全正确。正如其他回答所示,它确实是可以完成的,尽管看起来有些丑陋。 - Jesse Chisholm
设计师似乎不允许您指定通用集合类型。 - Quolonel Questions

2

您不能直接添加设置(至少不在运行时编辑配置XML),但可以伪造它。

在我的情况下,我在表单上有一组相同的自定义控件,并且我想存储每个控件的运行时状态。我需要存储每个控件的状态,因为每个控件都有不同的数据。

我创建了一个名为ControlData的新的StringCollection设置,并将自己的数据放入其中。然后,我从该列表中加载数据并用它来初始化我的控件。

该列表如下:

Box1Text=A
Box1List=abc;def;foo;bar;
Box2Text=hello
Box2List=server1;server2;

在我的启动代码中,我像这样读取键/值对:

foreach (string item in Properties.Settings.Default.ControlData) {
  string[] parts=item.split('=');

parts[0]将会有键,parts[1]将会有值。你现在可以根据这个数据进行操作。

在关闭阶段,我会反过来将数据写回列表。(遍历表单中的所有控件,并将它们的设置添加到ControlData中)。


这是一个有用的“解决方法”,但是Drew Ogle的解决方案适用于真正动态的属性。您可以使用以下代码再次访问它们:YourType YourVar = Properties.Settings.Default["YourName"] as YourType; - Jesse Chisholm

1

如何访问您创建的新设置?Visual Studio设置设计器的重点是,您可以编写使用这些设置的代码,并在编译时检查您的代码。如果您想动态创建应用程序要使用的新设置,则还需要动态加载它们。对于动态设置,您可能需要查看System.Configuration程序集,特别是ConfigurationSection。您可以使用它创建自定义配置部分,用于动态设置添加/删除。您可以使用ConfigurationCollection进行动态添加/删除。

INI文件?Google找到了this INI library适用于.NET。


访问方式类似于:YourType YourVar = Properties.Settings.Default["your_name"] as YourType; - Jesse Chisholm

1
你可以创建一个新的注册表键。 将新键命名为“你的程序设置”。
RegistryKey ProgSettings = Registry.CurrentUser.OpenSubKey("Software", true);
ProgSettings.CreateSubKey("Your Program settings");    
ProgSettings.Close();

现在您可以添加字符串标识符和值。
RegistryKey ProgSettings = Registry.CurrentUser.OpenSubKey("Software\\Your Program settings", true);
ProgSettings.SetValue("Setting Name", value); // store settings    
string settings = ProgSettings.GetValue("Setting Name", false); // retreave settings    
ProgSettings.DeleteValue("Setting Name", false);

在操作注册表时,请确保在完成后关闭注册表键,以避免与可能写入注册表的程序其他部分发生冲突。

许多商业软件应用程序使用这些方法。 stackoverflow有很多关于写入和读取注册表的示例。 这比修改创建设置时使用的appconfig.xml文件要容易得多。


1

我花了很长时间,使用这里的前两个答案,以及这个链接 (在运行时创建新设置,并在重启后读取) ,最终使其工作。

首先,设定你的期望。这里的答案将创建一个新的用户设置,下次启动应用程序时,您可以获取其值。然而,通过这种方式创建的设置不会出现在设置设计器中。实际上,当您重新启动应用程序并尝试在代码中访问设置时,它将找不到该设置。但是,您通过代码创建的设置已保存在用户配置文件中 (例如jDoe.config),保存在文件系统中的某个位置。为了访问这个值,您必须再次添加设置。

以下是我拥有的可行示例:

        private void FormPersistence_Load(object sender, EventArgs e)
        {
            StartPosition = FormStartPosition.Manual;
            // Set window location
            var exists = Settings.Default.Properties.OfType<SettingsProperty>().Any(p => p.Name == Name + "Location");
            if (exists)
            {
                this.Location = (Point)Settings.Default[Name + "Location"];
            }
            else
            {
                var property = new SettingsProperty(Settings.Default.Properties["baseLocation"]);
                property.Name = Name + "Location";
                Settings.Default.Properties.Add(property);
                Settings.Default.Reload();
                this.Location = (Point)Settings.Default[Name + "Location"];
            }
        }

注意: 我的新设置的名称将在运行时解析。名称实际上是this.Name,即表单的名称。这是一个其他表单可以继承的基本表单,因此所有子表单都将能够记住它们的位置。
baseLocation是我在设置设计器中手动创建的设置。我拥有的新设置与其类型相同。这样,我就不必在代码中担心提供程序、类型等问题。

0

我明白我原本想法是错误的。我正在将一个C++应用程序移植到C#,它有很多ini文件设置,我正在寻找一种快捷方式来添加它们。我有点懒。


1
实际上,您可以使用设置文件生成器,因为这些设置实际上不是动态的。 - OregonGhost

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接