TreeViewの多階層をBindで実装、スタイルを指定する

  • TreeView の ItemsSource に全体の配列をBindし、 HierarchicalDataTemplate の ItemsSource に、子要素をBindする
  • 各項目のスタイルは、TreeView.ItemContainerStyle に設定する
  • 子要素が1つでもあれば、展開(>)ボタンが表示される

MainWindow.xaml

<Window x:Class="WpfApp7.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:WpfApp7"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    
    <Grid>

        <TreeView ItemsSource="{Binding Mode=OneWay}">
            <TreeView.Style>
                <!-- TreeView自体のスタイル -->
                <Style TargetType="{x:Type TreeView}" BasedOn="{StaticResource MaterialDesignTreeView}">
                    <Setter Property="Background" Value="#FFF0F0F0"/>
                </Style>
            </TreeView.Style>

            <TreeView.ItemContainerStyle>
                <!-- TreeViewの各項目のスタイル -->
                <Style TargetType="{x:Type TreeViewItem}" BasedOn="{StaticResource MaterialDesignTreeViewItem}">
                    <Setter Property="Padding" Value="0"/>
                    <Setter Property="Background" Value="{Binding Path=BackColor, Mode=OneTime}"/>
                </Style>
            </TreeView.ItemContainerStyle>

            <TreeView.ItemTemplate>
                <!-- HierarchicalDataTemplate の ItemSource に、子階層をBind -->
                <HierarchicalDataTemplate DataType="local:TreeDataStructure" ItemsSource="{Binding Path=SubData, Mode=OneWay}">
                    <Label Content="{Binding Path=LabelTest, Mode=OneWay}" Foreground="{Binding Path=ForeColor, Mode=OneTime}"/>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>
        
    </Grid>
    
</Window>

MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;

namespace WpfApp7
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        private Random objRandom = new Random();

        public MainWindow()
        {
            InitializeComponent();

            CreateData();
        }

        private void CreateData()
        {
            List<TreeDataStructure> ArrayTreeData = new List<TreeDataStructure>();

            for (int i = 0; i < 10; i++)
            {
                TreeDataStructure objFirstTreeData = new TreeDataStructure();
                objFirstTreeData.LabelTest = string.Format("{0}", i);

                byte f_r = GetRandomByte();
                byte f_g = GetRandomByte();
                byte f_b = GetRandomByte();
                objFirstTreeData.ForeColor = new SolidColorBrush(Color.FromArgb(255, f_r, f_g, f_b));

                byte b_r = GetRandomByte();
                byte b_g = GetRandomByte();
                byte b_b = GetRandomByte();
                objFirstTreeData.BackColor = new SolidColorBrush(Color.FromArgb(128, b_r, b_g, b_b));

                for (int j = 0; j < 5; j++)
                {
                    TreeDataStructure objSecondTreeData = new TreeDataStructure();
                    objSecondTreeData.LabelTest = string.Format("{0}-{1}", i, j);
                    objSecondTreeData.ForeColor = new SolidColorBrush(Color.FromArgb(GetRandomByte(), f_r, f_g, f_b));
                    objSecondTreeData.BackColor = new SolidColorBrush(Color.FromArgb(GetRandomByte(), b_r, b_g, b_b));
                    objFirstTreeData.SubData.Add(objSecondTreeData);
                }

                ArrayTreeData.Add(objFirstTreeData);
            }

            this.DataContext = ArrayTreeData;
        }

        private byte GetRandomByte()
        {
            return BitConverter.GetBytes(objRandom.Next(256))[0];
        }
    }
}

TreeDataStructure.cs

using System.Collections.Generic;
using System.Windows.Media;

namespace WpfApp7
{
    public class TreeDataStructure
    {
        public string LabelTest { get; set; } = "";
        public List<TreeDataStructure> SubData { get; set; } = new List<TreeDataStructure>();
        public Brush ForeColor { get; set; } = new SolidColorBrush(Colors.Black);
        public Brush BackColor { get; set; } = new SolidColorBrush(Colors.White);
    }
}

App.xaml

<Application x:Class="WpfApp7.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfApp7"
             xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
             StartupUri="MainWindow.xaml">
    <Application.Resources>

        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>

                <!--MahApps-->
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Light.Steel.xaml" />

                <!--Material Design-->
                <materialDesign:BundledTheme BaseTheme="Light" PrimaryColor="Indigo" SecondaryColor="Indigo" />
                <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />

                <!--Material Design: MahApps統合設定 -->
                <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.MahApps;component/Themes/MaterialDesignTheme.MahApps.Fonts.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.MahApps;component/Themes/MaterialDesignTheme.MahApps.Flyout.xaml" />

            </ResourceDictionary.MergedDictionaries>

        </ResourceDictionary>

    </Application.Resources>
</Application>