##概要
WPF(C#)でツールを作成するにあたって、ツリー表示させる必要が出てきたため、そこで作成したサンプルコードを載せます。環境は以下の通りです。
- Visual Studio 2017
- NugetにPrism.Mvvmをインストール済み
以下はツールのキャプチャ画像であり、行追加ボタンを押して生成した"天財女王"の左にあるトグルボタンで子階層の表示・非表示を切り替えます。
##ソースコード
MainWindow.xaml
<Window x:Class="DataGridTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:DataGridTest"
mc:Ignorable="d"
Title="MainWindow" x:Name="WindowDataGrid" Height="350" Width="525">
<Window.DataContext>
<local:ViewModel/>
</Window.DataContext>
<StackPanel>
<Button Content="行追加" Click="Button_Click"/>
<DataGrid Name="dataGrid" CanUserAddRows="False" AutoGenerateColumns="False" ItemsSource="{Binding Data}">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ToggleButton Visibility="{Binding VisibleGroup}" IsChecked="{Binding IsOpen, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="名前" Binding="{Binding Name}" />
<DataGridTextColumn Header="年齢" Binding="{Binding Age}" />
</DataGrid.Columns>
</DataGrid>
</StackPanel>
</Window>
MainWindow.xaml.cs
using System.Windows;
namespace DataGridTest
{
/// <summary>
/// MainWindow.xaml の相互作用ロジック
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
// 行追加ボタン押下処理
private void Button_Click(object sender, RoutedEventArgs e)
{
var vm = this.DataContext as ViewModel;
if (null == vm) { return; }
// ツリー表示となるデータを追加する
vm.Add(new Person(vm._dumpData, vm.Data) { Name = "天財女王", Age = 57, VisibleGroup = Visibility.Visible });
}
}
}
Person.cs
using Microsoft.Practices.Prism.Mvvm;
using System.Collections.ObjectModel;
using System.Windows;
namespace DataGridTest
{
// DataGridに表示するデータ
public class Person : BindableBase
{
private ObservableCollection<Person> _Child;
private ObservableCollection<Person> _Parent;
// 名前
public string Name { get; set; }
// 年齢
private int _Age;
public int Age
{
get => _Age;
set
{
if (value < 0)
{
MessageBox.Show("範囲外の値が設定されました。");
OnPropertyChanged("Age");
}
else
{
SetProperty(ref _Age, value);
}
}
}
// 階層を展開するためのボタンの表示状態
public Visibility VisibleGroup { get; set; } = Visibility.Collapsed;
// 子階層を表示しているか否か
private bool _IsOpen = false;
public bool IsOpen
{
get => _IsOpen;
set
{
_IsOpen = value;
if (null != _Child)
{
// 子階層があれば、表示/非表示に応じて、データを挿入/削除する
if (_IsOpen)
{
int index = _Parent.IndexOf(this) + 1;
foreach (Person item in _Child)
{
_Parent.Insert(index, item);
}
}
else
{
int index = _Parent.IndexOf(this) + 1;
foreach (Person item in _Child)
{
_Parent.RemoveAt(index);
}
}
}
}
}
public Person() { }
// 子階層と親階層を設定する
public Person(ObservableCollection<Person> child, ObservableCollection<Person> parent)
{
_Child = child;
_Parent = parent;
}
}
}
ViewModel.cs
using Microsoft.Practices.Prism.Mvvm;
using System.Collections.ObjectModel;
using System.Windows;
namespace DataGridTest
{
public class ViewModel : BindableBase
{
// 子階層用のデータ
public ObservableCollection<Person> _dumpData = new ObservableCollection<Person>
{
new Person{Name=" 天財息子", Age=29},
new Person{Name=" 天財娘", Age=27}
};
// 初期データ
private ObservableCollection<Person> _Data = new ObservableCollection<Person>
{
new Person{Name="天財太郎", Age=19},
new Person{Name="天財次郎", Age=17}
};
public ObservableCollection<Person> Data
{
get => _Data;
set
{
SetProperty(ref _Data, value);
}
}
public void Add(Person data)
{
Data.Add(data);
Data[0].VisibleGroup = Visibility.Hidden;
}
}
}