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

質問
回答
-
どのように子項目を作ったかによって方法が変わります。
<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
すべての返信
-
どのように子項目を作ったかによって方法が変わります。
<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