Windows GUIプログラミング入門12 リストビュー(1)

# ■はじめに
今回はリストビューを使います。

キーワード：ListView, ObservableCollection

[注意]
これまでの回で説明済みの操作方法等は、説明を省略したり簡略化している場合があります。

# ■開発環境
* Windows 10
* Visual Studio Community 2017
* .NET Framework 4.x

# ■作ってみる

## ◇MainWindow（文字列の配列を表示）

`ListView`と`Button`を一つずつ配置します。
![wbg12-01.png](https://qiita-image-store.s3.amazonaws.com/0/142879/1a5749ae-8918-eb7c-e220-c146e5f8d174.png)

`ListView`を選択し、プロパティの「共通」 - 「View」 - `Columns`の「...」でコレクションエディターを開きます。
![wbg12-02.png](https://qiita-image-store.s3.amazonaws.com/0/142879/488065b8-abb7-69a7-d4ab-3553a65214b1.png)

1つ目の`GridViewColumn`の`Header`に「ID」と入力し、「追加」ボタンで2つ目を追加します。
![wbg12-03.png](https://qiita-image-store.s3.amazonaws.com/0/142879/277e89e3-90a9-15d6-c36f-a8caaa255794.png)

2つ目の`GridViewColumn`の`Header`に「名前」と入力します。
![wbg12-04.png](https://qiita-image-store.s3.amazonaws.com/0/142879/6743c134-57b9-1d4a-5b3c-7fb330d405b8.png)

`ListView`の`ItemsSource`の右端の`□`をクリックし、「データバインドの作成」を選択します。
![wbg12-05.png](https://qiita-image-store.s3.amazonaws.com/0/142879/a4976eae-f201-6402-f28b-032ff24f4c61.png)

「バインドの種類」に「データコンテキスト」を選択し、「OK」で閉じます。
![wbg12-06.png](https://qiita-image-store.s3.amazonaws.com/0/142879/ae627cb7-aefe-a8bf-1a98-8b2010656faf.png)
この操作で`ListView`に`ItemsSource="{Binding Mode=OneWay}"`が追加されます。

XamlでIDの`GridViewColumn`を選択し、`DisplayMemberBinding`右端の`□`から「データバインドの作成」を選択します。
![wbg12-07.png](https://qiita-image-store.s3.amazonaws.com/0/142879/15c83c1b-5acb-1f39-6d00-d96bec272b10.png)

「バインドの種類」に「データコンテキスト」を選択し、「パス」に`[0]`を入力して「OK」で閉じます。
![wbg12-08.png](https://qiita-image-store.s3.amazonaws.com/0/142879/e0d30360-634a-39cb-9677-a38cb5c4840d.png)

同じように名前の`GridViewColumn`も「パス」に`[1]`を入力します。
ここまででXamlの`GridViewColumn`は以下のようになっているはずです。

```Xml
<GridViewColumn Header="ID" DisplayMemberBinding="{Binding [0]}"/>
<GridViewColumn Header="名前" DisplayMemberBinding="{Binding [1]}"/>
```

コードビハインドにリストビューの項目を追加する処理を書きます。

```CSharp:MainWindow.xaml.cs
/// <summary>
/// コンストラクタ
/// </summary>
public MainWindow()
{
    InitializeComponent();

    listView.Items.Add(new string[] { "11", "たろう" });
    listView.Items.Add(new string[] { "12", "じろう" });
}
```

### <i class="fa fa-square-o" style="font-size:1em;"></i> 実行

実行してみます。
![wbg12-09.png](https://qiita-image-store.s3.amazonaws.com/0/142879/b7051204-2060-7a0a-cf66-771b2e172119.png)

### <i class="fa fa-square-o" style="font-size:1em;"></i> まとめ

```Xml:Xaml
<ListView x:Name="listView" ItemsSource="{Binding Mode=OneWay}">
    <ListView.View>
        <GridView>
            <!-- 配列の1つ目を表示 -->
            <GridViewColumn Header="列A" DisplayMemberBinding="{Binding [0]}"/>
            <!-- 配列の2つ目を表示 -->
            <GridViewColumn Header="列B" DisplayMemberBinding="{Binding [1]}"/>
        </GridView>
    </ListView.View>
</ListView>
```

```CSharp:コードビハインド
// 1行目
listView.Items.Add(new string[] { "列Aの値-1", "列Bの値-1" });
// 2行目
listView.Items.Add(new string[] { "列Aの値-2", "列Bの値-2" });
```

## ◇Window1（ユーザー定義クラスを表示）

ウィンドウを`×`ボタンで閉じます。
プロジェクトに新しいウィンドウを追加します。
名前は`Window1.xaml`にします。

`MainWindow`のボタンクリックイベントに`Window1`を表示する処理を書きます。

```CSharp:MainWindow.xaml.cs
private void button_Click(object sender, RoutedEventArgs e)
{
    var window = new Window1();
    window.Show();
}
```

`Window1`に`ListView`と`Button`を配置します。
![wbg12-10.png](https://qiita-image-store.s3.amazonaws.com/0/142879/366879f8-dc8f-aa9a-49bb-029d6c0388fc.png)

プロジェクトにクラスを追加します。
名前は`Person.cs`にします。

```CSharp:Person.cs
namespace WpfApp12
{
    public class Person
    {
        public int ID { get; set; }
        public string Name { get; set; }
    }
}
```

リストビューの一覧用のプロパティを追加し、コンストラクタに初期化処理を書きます。

```CSharp:Window1.xaml.cs
/// <summary>
/// Window1.xaml の相互作用ロジック
/// </summary>
public partial class Window1 : Window
{
    List<Person> Persons { get; set; }

    /// <summary>
    /// コンストラクタ
    /// </summary>
    public Window1()
    {
        InitializeComponent();

        this.Persons = new List<Person>();
        this.Persons.Add(new Person { ID = 33, Name = "さぶろー" });
        this.Persons.Add(new Person { ID = 44, Name = "しろー" });
        listView.DataContext = this.Persons;
    }
}
```

画面の方に戻ります。
先ほどと同じように`ListView`の「共通」 - 「View」 - `Columns`で`Header`が`ID`と`名前`の列を作り、
`ItemsSource`の「データバインドの作成」で「バインドの種類」に「データコンテキスト」を選択し、
IDの`DisplayMemberBinding`のデータバインドの作成で、「バインドの種類」に「データコンテキスト」、「パス」に`ID`を入力します。
![wbg12-11.png](https://qiita-image-store.s3.amazonaws.com/0/142879/5cc7d052-65e6-b877-5f6d-e93f87b78162.png)

名前の方は「パス」に`Name`を入力します。
![wbg12-12.png](https://qiita-image-store.s3.amazonaws.com/0/142879/6040dad3-c0c4-d2ef-5389-82b75d6e2779.png)

### <i class="fa fa-square-o" style="font-size:1em;"></i> 実行

実行してみます。`MainWindow`でボタンを押して`Window1`を表示します。
![wbg12-13.png](https://qiita-image-store.s3.amazonaws.com/0/142879/a7c5e9fe-0dd7-0441-6ba2-074926698279.png)

### <i class="fa fa-square-o" style="font-size:1em;"></i> まとめ

```Xml:Xaml
<ListView x:Name="listView" ItemsSource="{Binding Mode=OneWay}">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="列A" DisplayMemberBinding="{Binding FieldA}"/>
            <GridViewColumn Header="列B" DisplayMemberBinding="{Binding FieldB}"/>
        </GridView>
    </ListView.View>
</ListView>
```

```CSharp:コードビハインド
List<ClassX> ClassXList { get; set; }

  ：

this.ClassXList = new List<ClassX>();
this.ClassXList.Add(new ClassX { FieldA = 123, FieldB = "あああ" });
this.ClassXList.Add(new ClassX { FieldA = 456, FieldB = "いいい" });
listView.DataContext = this.ClassXList;
```

## ◇Window2（実行時のデータ更新）

起動したウィンドウを閉じて、プロジェクトに新しいウィンドウを追加します。
名前は`Window2.xaml`にします。

`Window1`のボタンクリック時に`Window2`を表示する処理を書きます。

```CSharp:Window1.xaml.cs
private void button_Click(object sender, RoutedEventArgs e)
{
    new Window2().Show();
}
```

`ListView`と`Button`を1つずつ配置し、`Button`の`Name`を`addButton`に、`Content`を`追加`にします。
（スクリーンショットではボタン2つですが、使うのは1つだけです。1つだけ配置してください。）
![wbg12-20.png](https://qiita-image-store.s3.amazonaws.com/0/142879/abcd37f8-7d43-bb3f-ed3f-e9080eff995b.png)

`Windows1`と同じように、`ListView`の`ItemsSource`, `GridViewColumn`の`Header`, `DisplayMemberBinding`を設定します。
![wbg12-21.png](https://qiita-image-store.s3.amazonaws.com/0/142879/9e0bc49b-2838-b10d-7518-df3a1bc80345.png)

コードビハインドで`ListView`のデータ表示元を定義します。

```CSharp:Window2.xaml.cs
using System;
using System.Collections.ObjectModel;   // ObservableCollection
using System.Windows;

namespace WpfApp12
{
    /// <summary>
    /// Window2.xaml の相互作用ロジック
    /// </summary>
    public partial class Window2 : Window
    {
        // 静的なリストではなく、実行時に追加や削除などの更新がある場合はObservableCollectionを使用する
        ObservableCollection<Person> Persons { get; set; }

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public Window2()
        {
            InitializeComponent();

            this.Persons = new ObservableCollection<Person>();
            listView.DataContext = this.Persons;
        }
    }
}
```

「追加」ボタンを押したときの処理を書きます。

```CSharp:Window2.xaml.cs
/// <summary>
/// 追加ボタンの処理
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
/// <remarks>
/// 一覧に要素を追加する。
/// </remarks>
private void addButton_Click(object sender, RoutedEventArgs e)
{
    // 100以上1000未満の乱数を取得
    int i = new Random().Next(100, 1000);

    // 一覧に要素追加
    this.Persons.Add(new Person { ID = i, Name = $"ユーザー{i}" });
}
```

### <i class="fa fa-square-o" style="font-size:1em;"></i> 実行

実行してみます。
`MainWindow` → `Window1` → `Window2`と表示します。
![wbg12-22.png](https://qiita-image-store.s3.amazonaws.com/0/142879/8c3795ec-307c-4fe3-de37-204b27d68034.png)

「追加」ボタンを押します。
![wbg12-23.png](https://qiita-image-store.s3.amazonaws.com/0/142879/c93ddd5d-7020-b844-7db1-d597fdb5642a.png)

もう一度「追加ボタンを押します。
![wbg12-24.png](https://qiita-image-store.s3.amazonaws.com/0/142879/5432a496-5173-bcd9-9c81-63eb12299877.png)

### <i class="fa fa-square-o" style="font-size:1em;"></i> まとめ

```Xml:Xaml
<ListView x:Name="listView" ItemsSource="{Binding Mode=OneWay}">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="列A" DisplayMemberBinding="{Binding FieldA}"/>
            <GridViewColumn Header="列B" DisplayMemberBinding="{Binding FieldB}"/>
        </GridView>
    </ListView.View>
</ListView>
```

```CSharp:コードビハインド
ObservableCollection<ClassX> ClassXList { get; set; }

  ：

this.ClassXList = new ObservableCollection<ClassX>();
listView.DataContext = this.ClassXList;

  ：

this.ClassXList.Add(new ClassX { FieldA = 999, FieldB = "ううう" });
```

おしまい

---

# ■参考サイト
* [ObservableCollection<T>クラス - MSDN](https://msdn.microsoft.com/ja-jp/library/ms668604.aspx)

---

[＜＜ 最初の記事](http://qiita.com/Kosen-amai/items/f9e3df2aa80363f5af5b "Windows GUIプログラミング入門1 メッセージボックス表示") 　 [＜ 前の記事](http://qiita.com/Kosen-amai/items/7835aac8df7cc925eddd "Windows GUIプログラミング入門11 設定保存(2)") 　 [次の記事 ＞](http://qiita.com/Kosen-amai/items/b07b9d7c905efdbaf6d7 "Windows GUIプログラミング入門13 リストビュー(2)、メニュー")