旧人類なのでUWPのDataGridにSQLで取得した値を設定したい！

# この記事は
UWPのDataGridへSQLで取得した値を設定したい旧人類のためのメモ

# ざっくり方法
ちなみに旧人類なのでVisual Studio 2017で試した。

## テスト用のテーブルを準備する

今回はSQLServerでデータベースを作成してUsersテーブルを準備した。

### Usersテーブル

|UserId|UserName|
|-----------------:|:------------------|
|1|山田　太郎|
|2|山田　次郎|
|3|山田　三郎|
|4|山田　四郎|
|5|山田　五郎|
|6|山田　六郎|
|7|山田　三四郎|
|8|山田　八郎|
|9|山田　九朗|
|10|山田　十郎|

## DataGridを使えるようにする
どうもUWPには標準でDataGridないみたい？
NuGetでMicrosoft.Toolkit.Uwp.Ui.Controls.DataGridをインストールする。
https://www.nuget.org/packages/Microsoft.Toolkit.Uwp.Ui.Controls.DataGrid/

インストールするとデザイナーのツールボックスへDataGridが追加される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348583/948df818-f5e0-b245-b224-91e7dee8d71b.png)

## コードを書く

```XML:MainPage.xaml
<Page
    x:Class="App1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App1"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:Custom="using:Microsoft.Toolkit.Uwp.UI.Controls"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid>
        <StackPanel Grid.Column="1">
            <Button Name="AddButton" Content="追加" Height="30" Margin="5,5,0,5" Click="AddButton_Click" />
            <Custom:DataGrid x:Name="UsersDataGrid" AutoGenerateColumns="False" ItemsSource="{Binding}">
            <Custom:DataGrid.Columns>
                <Custom:DataGridTextColumn Header="ＩＤ" Width="100" Binding="{Binding UserId}" />
                <Custom:DataGridTextColumn Header="氏名" Width="200" Binding="{Binding UserName}" />
            </Custom:DataGrid.Columns>
        </Custom:DataGrid>
        </StackPanel>
    </Grid>
</Page>
```

気を付ける点は
DataGridタグの
`AutoGenerateColumns="False"`[^1]
`ItemsSource="{Binding}"`
DataGridTextColumnタグの
`Binding="{Binding XXX}"`のXXXは、SQLのSELECT句のカラム名（DataColumnのColumnName）を設定する。

```CS:MainPage.xaml.cs
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.Data.SqlClient;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace App1
{
    public sealed partial class MainPage : Page
    {
        /// <summary>
        /// コンストラクター
        /// </summary>
        public MainPage()
        {
            this.InitializeComponent();

            // DataTableを取得
            string connectionString = "環境に合わせた接続文字列"; // 接続文字列
            string commandText = "SELECT UserId, UserName FROM Users"; // Usersテーブル取得SQL

            SqlDataAdapter adapter = new SqlDataAdapter(commandText, connectionString);
            DataTable table = new DataTable();
            adapter.Fill(table);

            // DataGridへセット
            UsersDataGrid.DataContext = ConvertDataTable(table);
        }

        /// <summary>
        /// DataTableをObservableCollectionへ変換する
        /// </summary>
        /// <param name="table">DataTable</param>
        /// <returns>ObservableCollectionへ変換されたDataTable</returns>
        private ObservableCollection<Dictionary<string, object>> ConvertDataTable(DataTable table)
        {
            ObservableCollection<Dictionary<string, object>> collection = new ObservableCollection<Dictionary<string, object>>();
            foreach (DataRow row in table.Rows)
            {
                Dictionary<string, object> dic = new Dictionary<string, object>();

                foreach (DataColumn column in table.Columns)
                {
                    dic[column.ColumnName] = row[column];
                }

                collection.Add(dic);
            }

            return collection;
        }

        /// <summary>
        /// 追加ボタンクリック
        /// </summary>
        /// <param name="sender">イベント発生元</param>
        /// <param name="e">Routedイベントデータ</param>
        private void AddButton_Click(object sender, RoutedEventArgs e)
        {
            ObservableCollection<Dictionary<string, object>> collection = (ObservableCollection<Dictionary<string, object>>)UsersDataGrid.DataContext;

            Dictionary<string, object> dic = new Dictionary<string, object>()
            {
                {"UserId", 0},
                {"UserName", "山田　零郎"}
            };

            collection.Insert(0, dic);
        }
    }
}
```

UsersDataGridのDataContextへ`DataTable`を設定しても期待した動作にならないので、
`ObservableCollection<Dictionary<string, object>>`[^2]に変換したものを設定する。

## 実行結果
### 起動時
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348583/330b7879-e59e-cc9e-72ee-fca7d3855aab.png)

SQLで取得した内容が表示された！

### 追加ボタンクリック時
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348583/fbfbf5ae-73b9-9663-e23a-03e1577d253d.png)

先頭に行が追加された！

# 最後に

結局のところ、旧人類はUWPなんて使わずにWindows Formsを使う。
[^1]: データが`Dictionary<string, object>`の場合、`AutoGenerateColumns="True"`にしても期待した動作にならない。
[^2]: `ObservableCollection<T>`ではなく`List<T>`でも表示はされるが、内容が変化した際にDataGridへ反映されない。