In my MVVM application I have a treeview that should bring a treeviewitem into view on selection. The treeview represents the records in a database. Each treeview item loads its children on demand by expanding the item when it is selected.
The treeview style is defined like this:
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="OverridesDefaultStyle" Value="True"/>
...
<EventSetter Event="Selected" Handler="OnTreeViewItemSelected"/>
The handler is defined like this:
private void OnTreeViewItemSelected(object sender, RoutedEventArgs e)
{
if (!Object.ReferenceEquals(sender, e.OriginalSource))
{
return;
}
TreeViewItem item = e.OriginalSource as TreeViewItem;
if (item != null)
{
EventHandler eventHandler = null;
eventHandler = new EventHandler(delegate
{
treeData.LayoutUpdated -= eventHandler;
item.BringIntoView();
});
treeData.LayoutUpdated += eventHandler;
}
}
This works perfectly well for items that are already loaded.
[Edit: in fact the parent of the selected item must be expanded rather than just loaded]
If they are loaded, the treeviewitems are iterated until the sought item is found, the found item is selected and the handler above successfully brings it into view.
The trouble is with items that are not already loaded. In these cases my code gets the ancestor records of the sought item, iterates through them expanding the items as it goes (and therefore loading the children) until it gets to the sought item. This is selected successfully, BUT does not get brought into view.
Does anyone know how to resolve this?
[UPDATE] In TreeViewItemViewModel:
public bool IsSelected
{
get { return _isSelected; }
set
{
if (value != _isSelected)
{
_isSelected = value;
if (value == true)
IsExpanded = value;
this.OnPropertyChanged("IsSelected");
}
}
}
public bool IsExpanded
{
get { return _isExpanded; }
set
{
if (_isExpanded == value)
return;
_isExpanded = value;
this.OnPropertyChanged("IsExpanded");
if (_isExpanded &&
_parent != null &&
_parent.IsExpanded == false)
_parent.IsExpanded = true;
LoadChildren();
}
}
LoadChildren() method handles whether the children require loading or not by using a flag.
ItemContainerStyle
Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"