I am having a problem getting the TreeViewItem
from a TreeView
with HierarchicalDataTemplate
. I want to search for an item by value and set IsExpanded to True, then select it.
I am using C# WPF with Visual Studio 2015 and Windows 10.
XAML Code :
<TreeView x:Name="TreeOres" SelectedItemChanged="TreeOres_SelectedItemChanged" Background="#f9f9f9" MinWidth="350" Width="auto" DockPanel.Dock="Left" ItemsSource="{Binding}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="local:Ores" ItemsSource="{Binding Path=resParent_Code_FK}">
<DockPanel LastChildFill="True" HorizontalAlignment="Stretch" Width="auto" Margin="0,5,0,5">
<Label Width="30" Height="30" DockPanel.Dock="Left" Uid="{Binding Path=Ores_ParentCode_FK}" Template="{StaticResource ImageTemp}"/>
<Label Content="{Binding Path=Ores_Name}" Width="250" DockPanel.Dock="Left"/>
<DockPanel.ContextMenu>
<ContextMenu>
<MenuItem Header="اضافة مجلد جديد + " x:Name="AddGroup" Click="AddGroup_Click" Uid="{Binding Path=Ores_Code}" />
<MenuItem Header="اضافة صنف جديد + " x:Name="AddItem" Click="AddItem_Click" Uid="{Binding Path=Ores_Code}" />
</ContextMenu>
</DockPanel.ContextMenu>
</DockPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
<TreeView.Resources>
<LinearGradientBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#FFD9F4FF" Offset="0"/>
<GradientStop Color="#FF9BDDFB" Offset="1"/>
</LinearGradientBrush>
<LinearGradientBrush x:Key="{x:Static SystemColors.ControlBrushKey}" EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#FFEEEDED" Offset="0"/>
<GradientStop Color="#FFDDDDDD" Offset="1"/>
</LinearGradientBrush>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black" />
<SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="Black" />
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
<Setter Property="IsExpanded" Value="True" />
</Style>
</TreeView.Resources>
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="BorderThickness" Value="1.5"/>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="BorderBrush" Value="#adc6e5"/>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontWeight" Value="Bold" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="True"/>
<Condition Property="IsSelectionActive" Value="False"/>
</MultiTrigger.Conditions>
<Setter Property="BorderBrush" Value="LightGray"/>
</MultiTrigger>
</Style.Triggers>
<Style.Resources>
<Style TargetType="Border">
<Setter Property="CornerRadius" Value="1"/>
</Style>
</Style.Resources>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
and C# code
class ClassTreeView
{
/// <summary>
/// Search in treeview by some value
/// </summary>
/// <param name="FilterColumn"></param>
/// <param name="FilterString"></param>
/// <param name="FilterColumnText"></param>
/// /// <param name="Result"></param>
///
public string FilterString { get; set; }
public string FilterColumn { get; set; }
public string FilterColumnText { get; set; }
public object Result { get; set; }
public DataTable mtable { get; set; }
public void SelectNodeById(TreeView Tree)
{
for (int i = 0; i < Tree.Items.Count; i++)
{
DataRowView row = Tree.Items[i] as DataRowView;
if (SearchInItem(row))
{
Tree.ItemsSource = null;
Tree.ItemsSource = mtable.DefaultView;
}
}
}
private bool SearchInItem(DataRowView item)
{
foreach (DataRowView obje in item.DataView)
{
if (SeaechNode(obje))
{
break;
}
SearchInItem(obje);
}
return false;
}
private bool SeaechNode(DataRowView row)
{
foreach (DataRowView dr in row.DataView)
{
dr.DataView.RowFilter = FilterColumn + "=" + FilterString;
if(dr != null)
{
return true;
}
}
return false;
}
}
This is full class code you can use this code :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Data;
using System.Windows.Media;
using System.Windows;
public string FilterString { get; set; } // Value searching
public string FilterColumn { get; set; } // column name
public string FilterColumnText { get; set; } // by this variable will display text
System.Windows.Threading.DispatcherTimer tmr = new System.Windows.Threading.DispatcherTimer(); // by this timer will search about an item becouse for going to next item we need to stop sometime
private int count = 0;
private int i = 0;
// will call to this method and adding treeview control to search about item
public void FindNode(TreeView tree = null)
{
tmr.Interval = new TimeSpan(0, 0, 0, 0, 1);
// will add count of objects
count = FindVisualChildren<DependencyObject>(tree).ToList().Count;
tmr.Tick += (s, e) =>
{
if (i < count)
{
if (FindVisualChildren<Grid>(tree).ToList()[i] != null)
{
Grid node = FindVisualChildren<Grid>(tree).ToList()[i];
if (SelectNode(node))
{
// if we found the item will stoping the timer
i = 0;
count = 0;
tmr.Stop();
}
}
i += 1;
}
// will add new count to the variable after expand the items
count = FindVisualChildren<Grid>(tree).ToList().Count;
};
tmr.Start();
}
// Search for an item
bool SelectNode(DependencyObject node)
{
bool fo = false;
for (int i = 0; i < (node as Grid).Children.Count; i++)
{
object obj = (node as Grid).Children[i];
if (obj.GetType() == typeof(Border))
{
TreeViewItem item = ((obj as Border).TemplatedParent as TreeViewItem);
if (item != null && item is TreeViewItem)
{
if (item.Items.Count > 0)
{
item.IsExpanded = true;
}
var row = item.Header as DataRowView;
if (row[FilterColumn].ToString() == FilterString)
{
item.IsSelected = true;
BindParent(item);
fo = true;
break;
}
items.Add(item);
}
}
}
return fo;
}
public IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
yield return (T)child;
foreach (T childOfChild in FindVisualChildren<T>(child))
yield return childOfChild;
}
}
}