web-dev-qa-db-ja.com

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>
67
Edward Tanguay

App.configファイルに独自のカスタム構成セクションを作成できます。 少数チュートリアルaround から始めましょう。最終的に、あなたはこのようなものを持つことができます:

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

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

リチャードの答えを補足するために、これはサンプル構成で使用できる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>;
116

単一の値でセミコロンで区切ることができます。

App.config

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

C#

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

私はリチャード・ニーナバーの答えが大好きですが、チューが指摘したように、リチャードが解決策として言及していることを達成するためにhowを実際には伝えません。したがって、私はあなたに私がこれを行う方法を提供することを選択し、リチャードが話している結果で終わりました。

ソリューション

この場合、どのオプションで挨拶する必要があるかを知る必要があるグリーティングウィジェットを作成します。これは、可能な将来のウィジェット用のコンテナも作成しているため、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プロパティ

コレクションGreetingWidgetCollectionConfigurationPropertygreetingWidgetとして定義して、結果の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;
31
Squazz

この目的のために、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
31
Ohad Schneider

同じ問題を抱えていましたが、別の方法で解決しました。それは最良の解決策ではないかもしれませんが、解決策です。

app.config:

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

次に、構成ラッパークラスで、キーを検索するメソッドを追加します。

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

これを読んでいる人にとっては、独自のカスタム構成セクションを作成する方がよりクリーンで安全であることに同意しますが、小さなプロジェクトでは、すぐに何かを必要とするため、これで解決するかもしれません。

9
ruffen

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);
5
Divya

質問ありがとう。しかし、私はこの問題に対する独自の解決策を見つけました。最初に、メソッドを作成しました

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