タイトルの通りですが、異なる要素をTreeViewで表示させる必要があったので、メモとして残します。
開発環境
あまり関係なさそうですが、開発環境も残しておきます。
- Visual studio 2019
- .Net Framework4.6.1
完成品
以下の画像のように、地域(関東、関西)、都道府県、市区町村を表示させます。
手順
まず地域、都道府県、市区町村を表すクラスを定義します。
using System.Collections.Generic;
namespace WpfApp
{
public interface ICategoryAndItem
{
string DispName { get; }
IList<ICategoryAndItem> Children { get; }
}
}
using System.Collections.Generic;
/// <summary>
/// 地域を表すクラス
/// </summary>
namespace WpfApp
{
public class Region : ICategoryAndItem
{
public string DispName { get; private set; }
/// <summary>
/// 地域に紐づく都道府県一覧
/// </summary>
public IList<ICategoryAndItem> Children { get; private set; }
public Region(string areaName)
{
DispName = areaName;
Children = new List<ICategoryAndItem>();
}
public Pref AddAndGetPref(string prefName)
{
var res = new Pref(this, prefName);
Children.Add(res);
return res;
}
}
}
using System.Collections.Generic;
/// <summary>
/// 都道府県を表すクラス
/// </summary>
namespace WpfApp
{
public class Pref : ICategoryAndItem
{
public Region Region { get; private set; }
public string DispName { get; private set; }
/// <summary>
/// 都道府県に紐づく市区町村一覧
/// </summary>
public IList<ICategoryAndItem> Children { get; private set; }
public Pref(Region region, string prefName)
{
Region = region;
DispName = prefName;
Children = new List<ICategoryAndItem>();
}
public Pref AddCityAndGetPref(string cityName)
{
Children.Add(new City(this, cityName));
return this;
}
}
}
using System.Collections.Generic;
/// <summary>
/// 市区町村を表すクラス
/// </summary>
namespace WpfApp
{
public class City : ICategoryAndItem
{
public Pref Pref { get; private set; }
public string DispName { get; private set; }
private readonly IList<ICategoryAndItem> EmptyList = new List<ICategoryAndItem>();
public IList<ICategoryAndItem> Children
{
get
{
return EmptyList;
}
}
public City(Pref pref, string cityName)
{
Pref = pref;
DispName = cityName;
}
}
}
WPFの都合上、各クラスを同じものとして扱う必要があるため(*1)、IFを定義しています。
次に、View周りを定義します。(長くなってしまったので、以降一部を抜粋しています。)
MainWIndow.xaml
<Window x:Class="WpfApp.MainWindow"
xmlns:local="clr-namespace:WpfApp">
<Grid>
<TreeView Name="TreeView">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="local:ICategoryAndItem" ItemsSource="{Binding Children}">
<TextBlock Text="{Binding DispName}" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
</Window>
MainWindow.xaml.cs
var kanto = new Region("関東");
kanto.AddAndGetPref("東京都")
.AddCityAndGetPref("港区")
.AddCityAndGetPref("文京区");
kanto.AddAndGetPref("千葉県")
.AddCityAndGetPref("千葉市")
.AddCityAndGetPref("木更津市");
var kansai = new Region("関西");
kansai.AddAndGetPref("大阪府")
.AddCityAndGetPref("大阪市")
.AddCityAndGetPref("福島区");
kansai.AddAndGetPref("兵庫県")
.AddCityAndGetPref("神戸市")
.AddCityAndGetPref("西宮市");
TreeView.ItemsSource = new List<ICategoryAndItem> { kanto, kansai };
MainWIndow.xamlでは、TreeViewの各要素(`Region`と`Children`の各要素)を`ICategoryAndItem`型として再帰的に表示させています。
また、市区町村は子要素を持たないので、空のListで返します。
以上。
参考
*1: WPF4.5入門 その26 「TreeViewコントロール その2」