如何从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);