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

下面的示例用我从代码中获得的 备份目录列表填充 物品控制

我如何更改它以便从 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>
189457 次浏览

You could have them semi-colon delimited in a single value, e.g.

App.config

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

C#

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

You can create your own custom config section in the app.config file. There are quite a few tutorials around to get you started. Ultimately, you could have something like this:

<configSections>
<section name="backupDirectories" type="TestReadMultipler2343.BackupDirectoriesSection, TestReadMultipler2343" />
</configSections>


<backupDirectories>
<directory location="C:\test1" />
<directory location="C:\test2" />
<directory location="C:\test3" />
</backupDirectories>

To complement Richard's answer, this is the C# you could use with his sample 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; }
}
}

Then you can access the backupDirectories configuration section as follows:

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

There's actually a very little known class in the BCL for this purpose exactly: CommaDelimitedStringCollectionConverter. It serves as a middle ground of sorts between having a ConfigurationElementCollection (as in Richard's answer) and parsing the string yourself (as in Adam's answer).

For example, you could write the following configuration section:

public class MySection : ConfigurationSection
{
[ConfigurationProperty("MyStrings")]
[TypeConverter(typeof(CommaDelimitedStringCollectionConverter))]
public CommaDelimitedStringCollection MyStrings
{
get { return (CommaDelimitedStringCollection)base["MyStrings"]; }
}
}

You could then have an app.config that looks like this:

<?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>

Finally, your code would look like this:

var section = (MySection)ConfigurationManager.GetSection("foo");
foreach (var s in section.MyStrings)
Console.WriteLine(s); //for example

Had the same problem, but solved it in a different way. It might not be the best solution, but its a solution.

in app.config:

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

Then in my configuration wrapper class, I add a method to search keys.

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

For anyone reading this, i agree that creating your own custom configuration section is cleaner, and more secure, but for small projects, where you need something quick, this might solve it.

I love Richard Nienaber's answer, but as Chuu pointed out, it really doesn't tell how to accomplish what Richard is refering to as a solution. Therefore I have chosen to provide you with the way I ended up doing this, ending with the result Richard is talking about.

The solution

In this case I'm creating a greeting widget that needs to know which options it has to greet in. This may be an over-engineered solution to OPs question as I am also creating an container for possible future widgets.

First I set up my collection to handle the different greetings

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

Then we create the acutal greeting element and it's interface

(You can omit the interface, that's just the way I'm always doing it.)

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

The greetingWidget property so our config understands the collection

We define our collection GreetingWidgetCollection as the ConfigurationProperty greetingWidget so that we can use "greetingWidget" as our container in the resulting XML.

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

The resulting 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>

And you would call it like this

List<GreetingElement> greetings = Widgets.GreetingWidget.All;

In App.config:

<add key="YOURKEY" value="a,b,c"/>

In C#:

string[] InFormOfStringArray = ConfigurationManager.AppSettings["YOURKEY"].Split(',').Select(s => s.Trim()).ToArray();
List<string> list = new List<string>(InFormOfStringArray);

Thank for the question. But I have found my own solution to this problem. At first, I created a method

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

Then I used this method to produce an instance of a class

var connStrs = GetSettingsWithDictionary<AuthMongoConnectionStrings>();

I have the next declaration of class

public class AuthMongoConnectionStrings
{
public Dictionary<string, string> ConnectionStrings { get; set; }
}

and I store my setting in App.config

<configuration>
<AuthMongoConnectionStrings
First="first"
Second="second"
Third="33" />
</configuration>

Found this thread when searching for how to get a list from appsettings.json.

{
"foo": {
"bar": [
"1",
"2",
"3"
]
}
}

There you can do it like this:

Configuration.GetSection("foo:bar").Get<List<string>>()

Source:

https://stackoverflow.com/a/42296371/3850405