How is it possible to programmatically select an item in a WPF TreeView? The ItemsControl model seems to prevent it.
I wrote a Helper class for this, which supports MVVM and lazy loaded items.
public class TreeViewHelper
{
public TreeViewHelper(TreeView treeView, Func getParent, Func> getSubItems)
{
TreeView = treeView;
GetParent = getParent;
GetSubItems = getSubItems;
}
public TreeView TreeView { get; }
public Func GetParent { get; }
public Func> GetSubItems { get; }
public void SelectItemWhileLoaded(TModel node, IList rootNodes)
{
if (TreeView.IsLoaded)
{
SelectItem(node, rootNodes);
}
else
{
TreeView.Loaded += TreeView_Loaded;
void TreeView_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
TreeView.Loaded -= TreeView_Loaded;
SelectItem(node, rootNodes);
}
}
}
public void SelectItem(TModel node, IList rootNodes)
{
Stack nodes = new Stack();
//push into stack
while (!rootNodes.Contains(node))
{
nodes.Push(node);
node = GetParent(node);
}
TreeViewItem treeViewItem = TreeView.ItemContainerGenerator
.ContainerFromItem(node) as TreeViewItem;
if (nodes.Count == 0)
{
//Top level
treeViewItem.IsSelected = true;
treeViewItem.BringIntoView();
return;
}
Expanded(true);
void Expanded(bool top)
{
if (!top)
{
treeViewItem = treeViewItem.ItemContainerGenerator
.ContainerFromItem(node) as TreeViewItem;
if (nodes.Count == 0)
{
treeViewItem.IsSelected = true;
treeViewItem.BringIntoView();
return;
}
}
node = nodes.Pop();
treeViewItem.IsExpanded = true;
if (treeViewItem.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
{
Expanded(true);
}
else
{
//Lazy
treeViewItem.ItemContainerGenerator.StatusChanged += ItemContainerGenerator_StatusChanged;
}
}
void ItemContainerGenerator_StatusChanged(object sender, EventArgs e)
{
if (treeViewItem.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
{
treeViewItem.ItemContainerGenerator.StatusChanged -= ItemContainerGenerator_StatusChanged;
Expanded(false);
}
}
}
}