none
TreeViewにC#コードから動的に追加した項目のフォントの色を変更したい

    質問

  • WPFのC#コードから動的に作ったTreeViewの子項目のフォントの色を、コードから変更するにはどうしたらいいのでしょうか?

    TreeView
    -Item1
    —ChildItem1 <-この項目のフォントの色を変えたい
    -Item2


    • 編集済み ttkk_737 2019年3月24日 1:52
    2019年3月20日 12:55

回答

  • どのように子項目を作ったかによって方法が変わります。

    <Window x:Class="WpfApp1.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:WpfApp1" mc:Ignorable="d"
            Title="MainWindow" Height="450" Width="800">
    
        <UniformGrid Columns="3" Rows="1">
            <GroupBox Header="TreeViewItemを追加してく場合" BorderThickness="3" Margin="5">
                <DockPanel>
                    <StackPanel DockPanel.Dock="Bottom">
                        <Button Content="追加" Click="AddTreeViewItem_Click" Margin="5"/>
                        <Button Content="色変更" Click="ChangeTreeViewItemForeground_Click" Margin="5"/>
                    </StackPanel>
    
                    <TreeView x:Name="treeView1" />
                </DockPanel>
            </GroupBox>
            
            <GroupBox Header="文字列を追加していく場合" BorderThickness="3" Margin="5">
                <DockPanel>
                    <StackPanel DockPanel.Dock="Bottom">
                        <Button Content="追加" Click="AddText_Click" Margin="5"/>
                        <Button Content="色変更" Click="ChangeTextColor_Click" Margin="5"/>
                    </StackPanel>
    
    
                    <TreeView x:Name="treeView2" >
                        <TreeView.ItemContainerStyle>
                            <Style TargetType="{x:Type TreeViewItem}">
                                <Setter Property="IsExpanded" Value="True" />
                            </Style>
                        </TreeView.ItemContainerStyle>
                    </TreeView>
                </DockPanel>
            </GroupBox>
    
            <GroupBox Header="ViewModeとしてNodeを追加していく場合" BorderThickness="3" Margin="5">
                <DockPanel>
                    <StackPanel DockPanel.Dock="Bottom">
                        <Button Content="追加" Click="AddNode_Click" Margin="5"/>
                        <Button Content="色変更" Click="ChangeNodeForeground_Click" Margin="5"/>
                    </StackPanel>
    
                    <TreeView x:Name="treeView3" >
                        <TreeView.ItemContainerStyle>
                            <Style TargetType="{x:Type TreeViewItem}">
                                <Setter Property="IsExpanded" Value="True" />
                                
                                <!-- Nodeのプロパティをバインドさせる -->
                                <Setter Property="ItemsSource" Value="{Binding Path=.}" />
                                <Setter Property="Header" Value="{Binding Path=Header}" />
                                <Setter Property="Foreground" Value="{Binding Path=Foreground,FallbackValue=Black}"/>
                            </Style>
                        </TreeView.ItemContainerStyle>
                    </TreeView>
                </DockPanel>
            </GroupBox>
        </UniformGrid>
    
    </Window>
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.ComponentModel;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Media;
    
    namespace WpfApp1
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
    
                CreateNodes1(this.treeView1);
                CreateNodes2(this.treeView2);
                CreateNodes3(this.treeView3);
            }
    
    
            #region "TreeViewにTreeViewItemを動的追加する場合"
            private void CreateNodes1(TreeView tv)
            {
                for (int i = 1; i <= 3; i++)
                {
                    TreeViewItem item = new TreeViewItem();
                    item.Header = "Item" + i.ToString();
                    item.IsExpanded = true;
                    tv.Items.Add(item);
                }
    
            }
    
            private void AddTreeViewItem_Click(object sender, RoutedEventArgs e)
            {
                //Itemsプロパティから子のTreeViewItemが取れる
                foreach (TreeViewItem item in this.treeView1.Items)
                {
                    if (item.Header.ToString() == "Item1")
                    {
                        //Itemsプロパティに子のTreeViewItemを追加
                        TreeViewItem child = new TreeViewItem();
                        child.Header = "ChildItem" + (item.Items.Count + 1).ToString();
                        item.Items.Add(child);
                    }
                }
            }
    
            private void ChangeTreeViewItemForeground_Click(object sender, RoutedEventArgs e)
            {
                string[] search = { "Item1", "ChildItem1" };
                ItemCollection items = this.treeView1.Items;
                TreeViewItem found = null;
                for (int depth = 0; depth < search.Length && items != null; depth++)
                {
                    found = null;
    
                    //Itemsプロパティから子のTreeViewItemが取れる
                    foreach (TreeViewItem item in items)
                    {
                        if (item.Header.ToString() == search[depth])
                        {
                            found = item;
                            break;
                        }
                    }
    
                    if (found != null)
                    {
                        items = found.Items;
                    }
                    else
                    {
                        break;
                    }
                }
    
                if (found != null)
                {
                    //目的のTreeViewItemのForegroundを変える
                    found.Foreground = CreateRundomBrush();
                }
            }
            #endregion
    
    
            #region "TreeViewにTreeViewItemではなくstringを動的追加していく場合"
    
            private void CreateNodes2(TreeView tv)
            {
                for (int i = 1; i <= 3; i++)
                {
                    tv.Items.Add("Item" + i.ToString());
                }
            }
    
            private void AddText_Click(object sender, RoutedEventArgs e)
            {
                for (int i = 0; i < this.treeView1.Items.Count; i++)
                {
                    //ItemsからはTreeViewItemを取れないので、ItemsContainerGeneratorでTreeViewItemを探す
                    TreeViewItem tvi = treeView2.ItemContainerGenerator.ContainerFromIndex(i) as TreeViewItem;
                    if (tvi != null && tvi.Header.ToString() == "Item1")
                    {
                        tvi.Items.Add("ChildItem" + (tvi.Items.Count + 1).ToString());
                    }
                }
            }
    
    
            private void ChangeTextColor_Click(object sender, RoutedEventArgs e)
            {
                string[] search = { "Item1", "ChildItem1" };
    
                ItemsControl parent = this.treeView2;
                TreeViewItem tvi = null;
                foreach (string text in search)
                {
                    //ItemsからはTreeViewItemを取れないので、ItemsContainerGeneratorでTreeViewItemを探す
                    tvi = parent.ItemContainerGenerator.ContainerFromItem(text) as TreeViewItem;
                    if (tvi == null)
                    {
                        break;
                    }
                    parent = tvi;
                }
    
                if (tvi != null)
                {
                    tvi.Foreground = CreateRundomBrush();
                }
            }
            #endregion
    
            #region "TreeViewItemにForegroudをバインドできるようにしてある場合"
            private void CreateNodes3(TreeView tv)
            {
                Node root = new Node();
                for (int i = 1; i <= 3; i++)
                {
                    Node item = new Node();
                    item.Header = "Item" + i.ToString();
    
                    root.Items.Add(item);
                }
    
                //TreeViewのItemsSourceにNodeを渡せば自動的にTreeViewItemに展開される
                tv.ItemsSource = root;
            }
    
            private void AddNode_Click(object sender, RoutedEventArgs e)
            {
                //動的追加は親NodeのItemsに子Nodeを追加していく
                foreach (Node item in this.treeView3.Items)
                {
                    if (item.Header.ToString() == "Item1")
                    {
                        Node child = new Node();
                        child.Header = "ChildItem" + (item.Items.Count + 1).ToString();
                        item.Items.Add(child);
                    }
                }
            }
    
            private void ChangeNodeForeground_Click(object sender, RoutedEventArgs e)
            {
                string[] search = { "Item1", "ChildItem1" };
    
                //目的のヘッダーを持つNodeを取り出す
                Node root = this.treeView3.ItemsSource as Node;
                IEnumerable<Node> nodes = root.Items;
                Node node = null;
                foreach (string header in search)
                {
                    node = nodes.FirstOrDefault(n => n.Header == header);
                    if (node == null)
                    {
                        break;
                    }
                    nodes = node.Items;
                }
    
                if (node != null)
                {
                    //NodeのForegroundにブラシを適用するとTreeViewItemにバインドされているので反映される
                    node.Foreground = CreateRundomBrush();
                }
            }
            #endregion
    
    
            private static SolidColorBrush CreateRundomBrush()
            {
                Random rnd = new Random();
                Byte[] bs = new byte[3];
                rnd.NextBytes(bs);
                Color color = Color.FromRgb(bs[0], bs[1], bs[2]);
                SolidColorBrush brush = new SolidColorBrush(color);
                return brush;
            }
        }
    
        //TreeViewItemに対応するViewModel
        class Node : IEnumerable, System.ComponentModel.INotifyPropertyChanged, System.Collections.Specialized.INotifyCollectionChanged
        {
            public Node()
            {
                Items = new System.Collections.ObjectModel.ObservableCollection<Node>();
                Foreground = System.Windows.Media.Brushes.Black;
            }
    
            public virtual string Header
            {
                get { return _Header; }
                set
                {
                    _Header = value;
                    OnProeprtyChanged("Header");
                }
    
            }
            public string _Header;
    
            public SolidColorBrush Foreground
            {
                get { return _Foreground; }
                set
                {
                    _Foreground = value;
                    OnProeprtyChanged("Foreground");
                }
            }
            private SolidColorBrush _Foreground;
    
            public Node this[string childHeader]
            {
                get
                {
                    return this.Items.OfType<Node>().FirstOrDefault(n => (string)n.Header == childHeader);
                }
            }
    
            #region 各種インターフェース
    
            public System.Collections.ObjectModel.ObservableCollection<Node> Items { get; private set; }
            public IEnumerator<Node> GetEnumerator()
            {
                return ((IEnumerable<Node>)Items).GetEnumerator();
            }
    
            IEnumerator IEnumerable.GetEnumerator()
            {
                return ((IEnumerable<Node>)Items).GetEnumerator();
            }
            public event NotifyCollectionChangedEventHandler CollectionChanged
            {
                add { ((INotifyCollectionChanged)Items).CollectionChanged += value; }
                remove { ((INotifyCollectionChanged)Items).CollectionChanged -= value; }
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
    
            protected virtual void OnProeprtyChanged(string name)
            {
                var pc = PropertyChanged;
                if (pc != null)
                {
                    pc(this, new PropertyChangedEventArgs(name));
                }
            }
    
    
            #endregion
        }
    
    
    }

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク ttkk_737 2019年3月24日 2:01
    2019年3月21日 1:24

すべての返信

  • どのように子項目を作ったかによって方法が変わります。

    <Window x:Class="WpfApp1.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:WpfApp1" mc:Ignorable="d"
            Title="MainWindow" Height="450" Width="800">
    
        <UniformGrid Columns="3" Rows="1">
            <GroupBox Header="TreeViewItemを追加してく場合" BorderThickness="3" Margin="5">
                <DockPanel>
                    <StackPanel DockPanel.Dock="Bottom">
                        <Button Content="追加" Click="AddTreeViewItem_Click" Margin="5"/>
                        <Button Content="色変更" Click="ChangeTreeViewItemForeground_Click" Margin="5"/>
                    </StackPanel>
    
                    <TreeView x:Name="treeView1" />
                </DockPanel>
            </GroupBox>
            
            <GroupBox Header="文字列を追加していく場合" BorderThickness="3" Margin="5">
                <DockPanel>
                    <StackPanel DockPanel.Dock="Bottom">
                        <Button Content="追加" Click="AddText_Click" Margin="5"/>
                        <Button Content="色変更" Click="ChangeTextColor_Click" Margin="5"/>
                    </StackPanel>
    
    
                    <TreeView x:Name="treeView2" >
                        <TreeView.ItemContainerStyle>
                            <Style TargetType="{x:Type TreeViewItem}">
                                <Setter Property="IsExpanded" Value="True" />
                            </Style>
                        </TreeView.ItemContainerStyle>
                    </TreeView>
                </DockPanel>
            </GroupBox>
    
            <GroupBox Header="ViewModeとしてNodeを追加していく場合" BorderThickness="3" Margin="5">
                <DockPanel>
                    <StackPanel DockPanel.Dock="Bottom">
                        <Button Content="追加" Click="AddNode_Click" Margin="5"/>
                        <Button Content="色変更" Click="ChangeNodeForeground_Click" Margin="5"/>
                    </StackPanel>
    
                    <TreeView x:Name="treeView3" >
                        <TreeView.ItemContainerStyle>
                            <Style TargetType="{x:Type TreeViewItem}">
                                <Setter Property="IsExpanded" Value="True" />
                                
                                <!-- Nodeのプロパティをバインドさせる -->
                                <Setter Property="ItemsSource" Value="{Binding Path=.}" />
                                <Setter Property="Header" Value="{Binding Path=Header}" />
                                <Setter Property="Foreground" Value="{Binding Path=Foreground,FallbackValue=Black}"/>
                            </Style>
                        </TreeView.ItemContainerStyle>
                    </TreeView>
                </DockPanel>
            </GroupBox>
        </UniformGrid>
    
    </Window>
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.ComponentModel;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Media;
    
    namespace WpfApp1
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
    
                CreateNodes1(this.treeView1);
                CreateNodes2(this.treeView2);
                CreateNodes3(this.treeView3);
            }
    
    
            #region "TreeViewにTreeViewItemを動的追加する場合"
            private void CreateNodes1(TreeView tv)
            {
                for (int i = 1; i <= 3; i++)
                {
                    TreeViewItem item = new TreeViewItem();
                    item.Header = "Item" + i.ToString();
                    item.IsExpanded = true;
                    tv.Items.Add(item);
                }
    
            }
    
            private void AddTreeViewItem_Click(object sender, RoutedEventArgs e)
            {
                //Itemsプロパティから子のTreeViewItemが取れる
                foreach (TreeViewItem item in this.treeView1.Items)
                {
                    if (item.Header.ToString() == "Item1")
                    {
                        //Itemsプロパティに子のTreeViewItemを追加
                        TreeViewItem child = new TreeViewItem();
                        child.Header = "ChildItem" + (item.Items.Count + 1).ToString();
                        item.Items.Add(child);
                    }
                }
            }
    
            private void ChangeTreeViewItemForeground_Click(object sender, RoutedEventArgs e)
            {
                string[] search = { "Item1", "ChildItem1" };
                ItemCollection items = this.treeView1.Items;
                TreeViewItem found = null;
                for (int depth = 0; depth < search.Length && items != null; depth++)
                {
                    found = null;
    
                    //Itemsプロパティから子のTreeViewItemが取れる
                    foreach (TreeViewItem item in items)
                    {
                        if (item.Header.ToString() == search[depth])
                        {
                            found = item;
                            break;
                        }
                    }
    
                    if (found != null)
                    {
                        items = found.Items;
                    }
                    else
                    {
                        break;
                    }
                }
    
                if (found != null)
                {
                    //目的のTreeViewItemのForegroundを変える
                    found.Foreground = CreateRundomBrush();
                }
            }
            #endregion
    
    
            #region "TreeViewにTreeViewItemではなくstringを動的追加していく場合"
    
            private void CreateNodes2(TreeView tv)
            {
                for (int i = 1; i <= 3; i++)
                {
                    tv.Items.Add("Item" + i.ToString());
                }
            }
    
            private void AddText_Click(object sender, RoutedEventArgs e)
            {
                for (int i = 0; i < this.treeView1.Items.Count; i++)
                {
                    //ItemsからはTreeViewItemを取れないので、ItemsContainerGeneratorでTreeViewItemを探す
                    TreeViewItem tvi = treeView2.ItemContainerGenerator.ContainerFromIndex(i) as TreeViewItem;
                    if (tvi != null && tvi.Header.ToString() == "Item1")
                    {
                        tvi.Items.Add("ChildItem" + (tvi.Items.Count + 1).ToString());
                    }
                }
            }
    
    
            private void ChangeTextColor_Click(object sender, RoutedEventArgs e)
            {
                string[] search = { "Item1", "ChildItem1" };
    
                ItemsControl parent = this.treeView2;
                TreeViewItem tvi = null;
                foreach (string text in search)
                {
                    //ItemsからはTreeViewItemを取れないので、ItemsContainerGeneratorでTreeViewItemを探す
                    tvi = parent.ItemContainerGenerator.ContainerFromItem(text) as TreeViewItem;
                    if (tvi == null)
                    {
                        break;
                    }
                    parent = tvi;
                }
    
                if (tvi != null)
                {
                    tvi.Foreground = CreateRundomBrush();
                }
            }
            #endregion
    
            #region "TreeViewItemにForegroudをバインドできるようにしてある場合"
            private void CreateNodes3(TreeView tv)
            {
                Node root = new Node();
                for (int i = 1; i <= 3; i++)
                {
                    Node item = new Node();
                    item.Header = "Item" + i.ToString();
    
                    root.Items.Add(item);
                }
    
                //TreeViewのItemsSourceにNodeを渡せば自動的にTreeViewItemに展開される
                tv.ItemsSource = root;
            }
    
            private void AddNode_Click(object sender, RoutedEventArgs e)
            {
                //動的追加は親NodeのItemsに子Nodeを追加していく
                foreach (Node item in this.treeView3.Items)
                {
                    if (item.Header.ToString() == "Item1")
                    {
                        Node child = new Node();
                        child.Header = "ChildItem" + (item.Items.Count + 1).ToString();
                        item.Items.Add(child);
                    }
                }
            }
    
            private void ChangeNodeForeground_Click(object sender, RoutedEventArgs e)
            {
                string[] search = { "Item1", "ChildItem1" };
    
                //目的のヘッダーを持つNodeを取り出す
                Node root = this.treeView3.ItemsSource as Node;
                IEnumerable<Node> nodes = root.Items;
                Node node = null;
                foreach (string header in search)
                {
                    node = nodes.FirstOrDefault(n => n.Header == header);
                    if (node == null)
                    {
                        break;
                    }
                    nodes = node.Items;
                }
    
                if (node != null)
                {
                    //NodeのForegroundにブラシを適用するとTreeViewItemにバインドされているので反映される
                    node.Foreground = CreateRundomBrush();
                }
            }
            #endregion
    
    
            private static SolidColorBrush CreateRundomBrush()
            {
                Random rnd = new Random();
                Byte[] bs = new byte[3];
                rnd.NextBytes(bs);
                Color color = Color.FromRgb(bs[0], bs[1], bs[2]);
                SolidColorBrush brush = new SolidColorBrush(color);
                return brush;
            }
        }
    
        //TreeViewItemに対応するViewModel
        class Node : IEnumerable, System.ComponentModel.INotifyPropertyChanged, System.Collections.Specialized.INotifyCollectionChanged
        {
            public Node()
            {
                Items = new System.Collections.ObjectModel.ObservableCollection<Node>();
                Foreground = System.Windows.Media.Brushes.Black;
            }
    
            public virtual string Header
            {
                get { return _Header; }
                set
                {
                    _Header = value;
                    OnProeprtyChanged("Header");
                }
    
            }
            public string _Header;
    
            public SolidColorBrush Foreground
            {
                get { return _Foreground; }
                set
                {
                    _Foreground = value;
                    OnProeprtyChanged("Foreground");
                }
            }
            private SolidColorBrush _Foreground;
    
            public Node this[string childHeader]
            {
                get
                {
                    return this.Items.OfType<Node>().FirstOrDefault(n => (string)n.Header == childHeader);
                }
            }
    
            #region 各種インターフェース
    
            public System.Collections.ObjectModel.ObservableCollection<Node> Items { get; private set; }
            public IEnumerator<Node> GetEnumerator()
            {
                return ((IEnumerable<Node>)Items).GetEnumerator();
            }
    
            IEnumerator IEnumerable.GetEnumerator()
            {
                return ((IEnumerable<Node>)Items).GetEnumerator();
            }
            public event NotifyCollectionChangedEventHandler CollectionChanged
            {
                add { ((INotifyCollectionChanged)Items).CollectionChanged += value; }
                remove { ((INotifyCollectionChanged)Items).CollectionChanged -= value; }
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
    
            protected virtual void OnProeprtyChanged(string name)
            {
                var pc = PropertyChanged;
                if (pc != null)
                {
                    pc(this, new PropertyChangedEventArgs(name));
                }
            }
    
    
            #endregion
        }
    
    
    }

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク ttkk_737 2019年3月24日 2:01
    2019年3月21日 1:24
  • ご回答ありがとうございます。
    思っていたことができました。
    2019年3月26日 11:06