如何从 WPF 中的 app.config 获取 List<string> 值集合?
Posted
技术标签:
【中文标题】如何从 WPF 中的 app.config 获取 List<string> 值集合?【英文标题】:How to get a List<string> collection of values from app.config in WPF? 【发布时间】:2010-12-19 05:51:45 【问题描述】:以下示例使用我从代码中获得的 BackupDirectories 列表填充 ItemsControl。
如何更改此设置以便从 app.config 文件中获得相同的信息?
XAML:
<Window x:Class="TestReadMultipler2343.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="160"/>
</Grid.ColumnDefinitions>
<TextBlock
Grid.Row="0"
Grid.Column="0"
Text="Title:"/>
<TextBlock
Grid.Row="0"
Grid.Column="1"
Text="Binding Title"/>
<TextBlock
Grid.Row="1"
Grid.Column="0"
Text="Backup Directories:"/>
<ItemsControl
Grid.Row="1"
Grid.Column="1"
ItemsSource="Binding BackupDirectories"/>
</Grid>
</Window>
代码隐藏:
using System.Collections.Generic;
using System.Windows;
using System.Configuration;
using System.ComponentModel;
namespace TestReadMultipler2343
public partial class Window1 : Window, INotifyPropertyChanged
#region ViewModelProperty: Title
private string _title;
public string Title
get
return _title;
set
_title = value;
OnPropertyChanged("Title");
#endregion
#region ViewModelProperty: BackupDirectories
private List<string> _backupDirectories = new List<string>();
public List<string> BackupDirectories
get
return _backupDirectories;
set
_backupDirectories = value;
OnPropertyChanged("BackupDirectories");
#endregion
public Window1()
InitializeComponent();
DataContext = this;
Title = ConfigurationManager.AppSettings.Get("title");
GetBackupDirectoriesInternal();
void GetBackupDirectoriesInternal()
BackupDirectories.Add(@"C:\test1");
BackupDirectories.Add(@"C:\test2");
BackupDirectories.Add(@"C:\test3");
BackupDirectories.Add(@"C:\test4");
void GetBackupDirectoriesFromConfig()
//BackupDirectories = ConfigurationManager.AppSettings.GetValues("backupDirectories");
#region INotifiedProperty Block
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
#endregion
app.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="title" value="Backup Tool" />
<!--<add key="backupDirectories">
<add value="C:\test1"/>
<add value="C:\test2"/>
<add value="C:\test3"/>
<add value="C:\test4"/>
</add>-->
</appSettings>
</configuration>
【问题讨论】:
最简单的解决方案是使用System.Collections.Specialized.StringCollection:回答问题:Store String Array In appSettings? 看看我的新答案***.com/a/29487138/105445 How to implement a ConfigurationSection with a ConfigurationElementCollection的可能重复 似乎在***.com/a/32637544/69663也得到了回答 【参考方案1】:您可以将它们用分号分隔在单个值中,例如
App.config
<add key="paths" value="C:\test1;C:\test2;C:\test3" />
C#
var paths = new List<string>(ConfigurationManager.AppSettings["paths"].Split(new char[] ';' ));
【讨论】:
如果您不需要自定义配置部分的开销,这是一种快速的方法。这已经足够 IMO 了。 这是我的想法...自定义配置部分非常好用且功能强大,但对于简单的字符串数组来说可能有点过分了。 这是我长期以来一直这样做的方式......今天我正在转换为配置部分,因为管理我的列表(它是要加载的插件类列表,可以更改取决于环境)已经被 30 多个字符串弄乱了。 这个解决方案真是个好主意。当我想编辑配置时不太好 - 删除一些路径。添加不是问题。 呃。很好的解决方案,但只需要提及您必须添加 System.Configuration 作为参考(不能只使用“使用”)才能访问 ConfigurationManager。【参考方案2】:您可以在 app.config 文件中创建自己的自定义配置部分。有很多 few tutorials around 可以帮助您入门。最终,您可能会得到这样的结果:
<configSections>
<section name="backupDirectories" type="TestReadMultipler2343.BackupDirectoriesSection, TestReadMultipler2343" />
</configSections>
<backupDirectories>
<directory location="C:\test1" />
<directory location="C:\test2" />
<directory location="C:\test3" />
</backupDirectories>
为了补充 Richard 的回答,这是您可以与他的示例配置一起使用的 C#:
using System.Collections.Generic;
using System.Configuration;
using System.Xml;
namespace TestReadMultipler2343
public class BackupDirectoriesSection : IConfigurationSectionHandler
public object Create(object parent, object configContext, XmlNode section)
List<directory> myConfigObject = new List<directory>();
foreach (XmlNode childNode in section.ChildNodes)
foreach (XmlAttribute attrib in childNode.Attributes)
myConfigObject.Add(new directory() location = attrib.Value );
return myConfigObject;
public class directory
public string location get; set;
然后您可以访问backupDirectories配置部分,如下所示:
List<directory> dirs = ConfigurationManager.GetSection("backupDirectories") as List<directory>;
【讨论】:
是我遗漏了什么,还是这三个教程都没有真正向您展示如何拥有一个元素列表? @Chuu 查看此页面上的示例:msdn.microsoft.com/en-us/library/… @Demodave 你可以随时查看我的答案:***.com/a/33544322/1955317 这里我提供了执行 Richard 所说的所需的 C# 代码 :) @Demodave,C# 代码在我回答的教程链接中。 当我使用上面相同的代码时,我收到以下错误:无法加载文件或程序集“命名空间”或其依赖项之一。系统找不到指定的文件【参考方案3】:实际上,BCL 中有一个鲜为人知的类用于此目的:CommaDelimitedStringCollectionConverter。它充当拥有ConfigurationElementCollection
(如理查德的回答)和自己解析字符串(如亚当的回答)之间的某种中间立场。
例如,您可以编写以下配置部分:
public class MySection : ConfigurationSection
[ConfigurationProperty("MyStrings")]
[TypeConverter(typeof(CommaDelimitedStringCollectionConverter))]
public CommaDelimitedStringCollection MyStrings
get return (CommaDelimitedStringCollection)base["MyStrings"];
然后你可以有一个如下所示的 app.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="foo" type="ConsoleApplication1.MySection, ConsoleApplication1"/>
</configSections>
<foo MyStrings="a,b,c,hello,world"/>
</configuration>
最后,您的代码将如下所示:
var section = (MySection)ConfigurationManager.GetSection("foo");
foreach (var s in section.MyStrings)
Console.WriteLine(s); //for example
【讨论】:
我不知道你为什么要创建一个自定义部分,然后将其限制为一个分隔字符串;然而,这是我从未见过或不知道的。这是一个有趣的想法并且有据可查,感谢提供!【参考方案4】:有同样的问题,但以不同的方式解决了。它可能不是最好的解决方案,但它是一个解决方案。
在 app.config 中:
<add key="errorMailFirst" value="test@test.no"/>
<add key="errorMailSeond" value="krister@tets.no"/>
然后在我的配置包装类中,我添加了一个搜索键的方法。
public List<string> SearchKeys(string searchTerm)
var keys = ConfigurationManager.AppSettings.Keys;
return keys.Cast<object>()
.Where(key => key.ToString().ToLower()
.Contains(searchTerm.ToLower()))
.Select(key => ConfigurationManager.AppSettings.Get(key.ToString())).ToList();
对于阅读本文的任何人,我同意创建自己的自定义配置部分更清洁、更安全,但对于需要快速操作的小型项目,这可能会解决问题。
【讨论】:
...除了您可以直接查询AppSettings.Keys
以获得字符串相等性之外,为什么要转换为object
,然后再转换回string
?
考虑到这是我 4 年前写的,我不记得了。当我现在看到它时,演员看起来没有必要。【参考方案5】:
我喜欢 Richard Nienaber 的回答,但正如 Chuu 指出的那样,它确实没有告诉 如何 完成 Richard 所说的解决方案。 因此,我选择向您提供我最终这样做的方式,以理查德所说的结果结束。
解决方案
在这种情况下,我正在创建一个问候小部件,它需要知道它必须在哪些选项中打招呼。这可能是针对 OP 问题的过度设计的解决方案,因为我还在为可能的未来小部件创建一个容器。
首先我设置我的集合来处理不同的问候
public class GreetingWidgetCollection : System.Configuration.ConfigurationElementCollection
public List<IGreeting> All get return this.Cast<IGreeting>().ToList();
public GreetingElement this[int index]
get
return base.BaseGet(index) as GreetingElement;
set
if (base.BaseGet(index) != null)
base.BaseRemoveAt(index);
this.BaseAdd(index, value);
protected override ConfigurationElement CreateNewElement()
return new GreetingElement();
protected override object GetElementKey(ConfigurationElement element)
return ((GreetingElement)element).Greeting;
然后我们创建实际的问候元素和它的界面
(界面可以省略,我一直都是这样。)
public interface IGreeting
string Greeting get; set;
public class GreetingElement : System.Configuration.ConfigurationElement, IGreeting
[ConfigurationProperty("greeting", IsRequired = true)]
public string Greeting
get return (string)this["greeting"];
set this["greeting"] = value;
greetingWidget 属性,以便我们的配置理解集合
我们将集合 GreetingWidgetCollection
定义为 ConfigurationProperty
greetingWidget
,以便我们可以在生成的 XML 中使用“greetingWidget”作为我们的容器。
public class Widgets : System.Configuration.ConfigurationSection
public static Widgets Widget => ConfigurationManager.GetSection("widgets") as Widgets;
[ConfigurationProperty("greetingWidget", IsRequired = true)]
public GreetingWidgetCollection GreetingWidget
get return (GreetingWidgetCollection) this["greetingWidget"];
set this["greetingWidget"] = value;
生成的 XML
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<widgets>
<greetingWidget>
<add greeting="Hej" />
<add greeting="Goddag" />
<add greeting="Hello" />
...
<add greeting="Konnichiwa" />
<add greeting="Namaskaar" />
</greetingWidget>
</widgets>
</configuration>
你会这样称呼它
List<GreetingElement> greetings = Widgets.GreetingWidget.All;
【讨论】:
GreetingWidget 属性在哪里? @Rhyous 我更新了我的答案以澄清这一点。但这也很大程度上取决于您为您的案例修改了多少代码:) @Squazz 我想他可能一直在问应该在哪里定义 C#GreetingWidget
属性。我假设打算将其添加到 GreetingWidgetCollection
类中?
@Squazz 我之所以提到这一点,是因为我对此也感到困惑。不过,我仍然无法让它为我工作。每次我尝试从集合中读取数据时,都会出现堆栈溢出异常。我假设它的用法只是:List<IGreeting> greetingWidgets = new GreetingWidgetCollection().GreetingWidget.All;
?另外,section
需要如何在 app.config
configSections
节点中定义?像这样:<section name="greetingWidget" type="WidgetApp.GreetingWidgetCollection, GreetingWidget"/>
?
@Squazz 是的,这就是我要问的。在你回复之前我就想通了。我得到了它的工作。【参考方案6】:
在 App.config 中:
<add key="YOURKEY" value="a,b,c"/>
在 C# 中:
string[] InFormOfStringArray = ConfigurationManager.AppSettings["YOURKEY"].Split(',').Select(s => s.Trim()).ToArray();
List<string> list = new List<string>(InFormOfStringArray);
【讨论】:
非常好,但我有一个问题,我对将这些值放入数组然后将它们放入列表的原因感到有些困惑,而您可以简单地使用 .ToList() 代替? 【参考方案7】:感谢您的提问。但我已经找到了解决这个问题的方法。 一开始,我创建了一个方法
public T GetSettingsWithDictionary<T>() where T:new()
IConfigurationRoot _configurationRoot = new ConfigurationBuilder()
.AddXmlFile($"Assembly.GetExecutingAssembly().Location.config", false, true).Build();
var instance = new T();
foreach (var property in typeof(T).GetProperties())
if (property.PropertyType == typeof(Dictionary<string, string>))
property.SetValue(instance, _configurationRoot.GetSection(typeof(T).Name).Get<Dictionary<string, string>>());
break;
return instance;
然后我用这个方法生成了一个类的实例
var connStrs = GetSettingsWithDictionary<AuthMongoConnectionStrings>();
我有下一个类的声明
public class AuthMongoConnectionStrings
public Dictionary<string, string> ConnectionStrings get; set;
我将我的设置存储在 App.config 中
<configuration>
<AuthMongoConnectionStrings
First="first"
Second="second"
Third="33" />
</configuration>
【讨论】:
【参考方案8】:在搜索如何从appsettings.json
获取列表时发现此线程。
"foo":
"bar": [
"1",
"2",
"3"
]
你可以这样做:
Configuration.GetSection("foo:bar").Get<List<string>>()
来源:
https://***.com/a/42296371/3850405
【讨论】:
你不能真正将它用于 app.config,因为应用程序配置使用 xml 而不是 json。而且创建自定义json文件效率不高以上是关于如何从 WPF 中的 app.config 获取 List<string> 值集合?的主要内容,如果未能解决你的问题,请参考以下文章
在WPF程序运行时动态修改app.config文件后如何立即生效
WPF Core - App.config 中的连接字符串不起作用
从 c# 中的 app.config 获取 ConnectionString [重复]