如何从WPF中的app.config获取List <string>值的集合?

以下示例使用从代码获取的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> 

您可以在app.config文件中创build自己的自定义configuration部分。 有相当多的 教程 ,让你开始。 最终,你可以有这样的事情:

 <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#,你可以使用他的示例configuration:

 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; } } } 

然后,您可以按如下方式访问backupDirectoriesconfiguration部分:

 List<directory> dirs = ConfigurationManager.GetSection("backupDirectories") as List<directory>; 

你可以让他们在一个单一的值分号分号,例如

App.config中

 <add key="paths" value="C:\test1;C:\test2;C:\test3" /> 

C#

 var paths = new List<string>(ConfigurationManager.AppSettings["paths"].Split(new char[] { ';' })); 

实际上BCL中有一个非常less的已知类: CommaDelimitedStringCollectionConverter 。 它在ConfigurationElementCollection (如Richard的答案)和parsingstring(就像在Adam的回答中)之间起着种种中间的作用。

例如,你可以写下面的configuration部分:

 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 

我喜欢Richard Nienaber的回答,但正如Chuu指出的那样,实际上并没有告诉Richard 如何完成Richard所说的解决scheme。 所以我select给你提供这样的结果,最后是理查德正在谈论的结果。

解决scheme

在这种情况下,我创build了一个问候窗口小部件,它需要知道哪些选项需要打招呼。这可能是OPs问题的过度devise解决scheme,因为我也在为将来的小部件创build一个容器。

首先,我设立我的collections处理不同的问候

 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; } } 

然后我们创build一个acutal问候元素,它是界面

(你可以省略界面,这就是我一直这样做的方式。)

 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属性让我们的configuration理解集合

我们将我们的集合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; 

有同样的问题,但以不同的方式解决它。 这可能不是最好的解决scheme,但它是一个解决scheme。

在app.config中:

 <add key="errorMailFirst" value="test@test.no"/> <add key="errorMailSeond" value="krister@tets.no"/> 

然后在我的configuration包装类,我添加一个方法来search键。

  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(); } 

对于阅读这篇文章的人来说,我同意创build自己的自定义configuration部分更清洁,更安全,但对于小型项目,如果您需要快速的部分,这可能会解决这个问题。

在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);