かきスタンプ

福岡でフリーランスの物流系のエンジニアやってます。

WPF:DataGrid の ItemsSource に、配列データを設定すると妙な出力結果になるんで、その場合は ListView を使おうという話

郵便番号/住所/緯度経度データ等の地理情報を、XML or JSON で取得できるサービス『HeartRails Geo API』にて、エリア情報を叩くと、こういう値が返ってきます。

{
    "response": {
        "area": [
            "北海道",
            "東北",
            "関東",
            "中部",
            "近畿",
            "中国",
            "四国",
            "九州"
        ]
    }
}

この結果を、グリッドの ItemsSource に流し込んで、いい感じに表示しようと思い、以下のように書いたら、何とも微妙な結果になりました。  
 
Http リクエストを投げるところと、デシリアライズのところは省略しています。
また、受け側は dynamic型にしています。
(フォーム部分は省略しています。といっても、「myDataGrid01」という Name の DataGrid があれば何でもいい訳ですが。)

csソース1
List<dynamic> areaList = new List<dynamic>();
foreach (var item in responseData.response.area) // 「responseData」にデシリアライズされたデータが格納されています。
{
    areaList.Add(item);
}
myDataGrid01.ItemsSource = areaList;
実行結果1

f:id:kakisoft:20180430193003p:plain  
余計なものが色々入ってます。 必用なのは Valueなので、指定して抽出。

csソース2
List<dynamic> areaList = new List<dynamic>();
foreach (var item in responseData.response.area)
{
    areaList.Add(item.Value);
}
myDataGrid01.ItemsSource = areaList;
実行結果2

f:id:kakisoft:20180430193006p:plain  

なぜか Lengthが取れるという妙な結果に・・・。
json のパースの仕方がどうこうという訳でなく、DataGrid の ItemsSource に、配列を放り込むと、こうなるみたいです。
なので、List<string> のデータでも、同様の現象が起こります。

対策

どうしても DataGridで表現しなければならないなら、配列の部分を Dictionaryにする or 自作のクラスを定義して、それに放り込むかですが、本来のデータに不純物を入れ込む事になるので、ちょっと避けたい。

という訳で、こういった場合は DataGridでなく、ListView を使う方法が最良ではないでしょうか。
以下では、「myListView01」という Name の ListView を定義しています。

csソース3
List<dynamic> areaList = new List<dynamic>();
foreach (var item in responseData.response.area)
{
    areaList.Add(item);
}
myListView01.ItemsSource = areaList;
実行結果3

f:id:kakisoft:20180430193009p:plain  
 
 
DataGrid は色々できて便利なんですが、その分操作が難しかったり、変にバッドノウハウを知っておかないとハマる原因になったりするので、やる事がシンプルなら、ListViewでいい気がします。