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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1779117/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 20:44:51  来源:igfitidea点击:

How to get a List<string> collection of values from app.config in WPF?

c#wpfitemscontrolapp-config

提问by Edward Tanguay

The following example fills the ItemsControlwith a List of BackupDirectorieswhich I get from code.

以下示例使用我从代码中获取的BackupDirectories列表填充ItemsControl

How can I change this so that I get the same information from the app.config file?

如何更改此设置以便从 app.config 文件中获取相同的信息?

XAML:

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>

code-behind:

代码隐藏:

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>

采纳答案by Richard Nienaber

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

您可以在 app.config 文件中创建自己的自定义配置部分。有相当一些教程身边让你开始。最终,你可能有这样的事情:

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

为了补充理查德的回答,这是您可以与他的示例配置一起使用的 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; }
    }
}

Then you can access the backupDirectories configuration section as follows:

然后您可以按如下方式访问备份目录配置部分:

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

回答by Adam Ralph

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#

C#

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

回答by Ohad Schneider

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).

实际上,BCL 中有一个鲜为人知的类就是用于此目的:CommaDelimitedStringCollectionConverter。它充当具有ConfigurationElementCollection(如理查德的答案)和自己解析字符串(如亚当的答案)之间的各种中间立场。

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:

然后你可以有一个看起来像这样的 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>

Finally, your code would look like this:

最后,您的代码将如下所示:

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

回答by ruffen

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:

在 app.config 中:

<add key="errorMailFirst" value="[email protected]"/>
<add key="errorMailSeond" value="[email protected]"/>

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.

对于阅读本文的任何人,我同意创建自己的自定义配置部分更简洁、更安全,但对于小型项目,您需要快速进行一些操作,这可能会解决问题。

回答by Squazz

I love Richard Nienaber's answer, but as Chuu pointed out, it really doesn't tell howto 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.

我喜欢 Richard Nienaber 的回答,但正如 Chuu 指出的那样,它确实没有说明如何完成 Richard 所说的解决方案。因此,我选择向您提供我最终这样做的方式,以 Richard 所说的结果结束。

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.

在这种情况下,我正在创建一个问候小部件,它需要知道它必须打招呼的选项。这可能是对 OP 问题的过度设计的解决方案,因为我也在为可能的未来小部件创建一个容器。

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

greetingWidget 属性让我们的配置理解集合

We define our collection GreetingWidgetCollectionas the ConfigurationPropertygreetingWidgetso that we can use "greetingWidget" as our container in the resulting XML.

我们将我们的集合定义GreetingWidgetCollection为 ,ConfigurationPropertygreetingWidget以便我们可以在结果 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; }
    }
}

The resulting XML

结果 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;

回答by Divya

In App.config:

在 App.config 中:

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

In C#:

在 C# 中:

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

回答by Larissa Savchekoo

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

我将我的设置存储在 App.config 中

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