Windows Form ComboBox.DataSource に紐づけた集合を更新する

# Windows Form ComboBox.DataSource に紐づけた集合を更新する

`DataSource` プロパティを使う場合のデータソース更新の反映方法をまとめてみた。

>本音を言えば C# でも `#define` を使えるようになっていたことを発見したのがうれしくて作った気がする。
注意点は、どのキーワードよりも前に書かなければならないこと。有効範囲はファイル単位。

参考記事
[Compiler Error CS1032](https://technet.microsoft.com/en-us/subscriptions/47hya4cw(v=vs.90).aspx)

```csharp
#define DEFINE1

using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace WinFormAsync
{
    public partial class UserControl1 : UserControl
    {
        private List<string> stringList = new List<string> { "abc", "123" };

        // 2016-12-19 追記
        // List<T> の代わりに System.ComponentModel.BindingList<T> を使えばリストを更新するだけでコントロールも更新されるようです。機能は少々ゴテっとしていますが。
        // private BindingList<string> stringList = new BindingList<string> { "abc", "123" };

        public UserControl1()
        {
            InitializeComponent();

            comboBox1.DataSource = stringList;
        }

        private void button1_Click(object sender, EventArgs e)
        {

#if DEFINE1

            // 全体入れ替え - アイテムに x, y が追加される
            
            // DataSource (List<string>) と ComboBox を直結
            stringList.AddRange(new List<string> { "x", "y" });

            // ComboBox を更新、null 代入が必要
            comboBox1.DataSource = null;
            comboBox1.DataSource = stringList;


#elif DEFINE2

            // 全体入れ替え - アイテム x, y が追加される

            // DataSource (List<string>) と ComboBox を直結
            var newList = new List<string> { "x", "y" };

            // ComboBox を更新
            comboBox1.DataSource = newList;

#elif DEFINE3

            //// 全体入れ替え - アイテムに def が追加される
            // List<> と ComboBox の間に BindingSource をかます

            var bindingSource1 = new BindingSource(stringList, "");
            comboBox1.DataSource = bindingSource1;

            // データソースに def を追加して
            stringList.Add("def");

            // ComboBox を更新
            bindingSource1.ResetBindings(false);

#else
            // 項目更新
            // List<> と ComboBox の間に BindingSource をかます
            var bindingSource1 = new BindingSource(stringList, "");
            comboBox1.DataSource = bindingSource1;

            stringList[0] = "ooo";
            bindingSource1.ResetItem(0);
#endif
        }

        // 12-06-2016 追加
        // string ではなくユーザデータを DataSource に。
        private List<UserData> userDataList = new List<UserData>
        {
            new UserData { Id = 1, Name = "taro", Memo = "taromemo" },
            new UserData { Id = 2, Name = "hanako", Memo = "hanakomemo"}
        };

        private void button2_Click(object sender, EventArgs e)
        {
            comboBox1.DataSource = userDataList;
            comboBox1.ValueMember = "Memo";
            comboBox1.DisplayMember = "Name";
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            Debug.WriteLine(comboBox1.SelectedValue);
        }
    }

    public class UserData
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Memo { get; set; }
    }
}
```

## 確認した環境

OS: 日本語 Windows 10 Home 64ビット
コンパイラ: Microsoft Visual Studio Community 2015 Update 3