I have a RadTreeView using a templated ItemsSource bound to a node collection in the view model. I have implemented a search on the tree, and the found node is programmatically selected within the view model (there is no code in the view). Do you have an example of how to bring the selected node into view using this type of MVVM structure?
Thanks for any help.
4 Answers, 1 is accepted

Edit: Still having a problem with collapsed items. I try calling expand on all nodes in the path before selecting and bringing into view, but the item is not within view when all is done.

When the tree is first loaded and not expanded, BringItemIntoView does not work on an item that is within a collapsed node (I assume this is an item that is not "immediate"). However, if the item is expanded into view at least once, then BringItemIntoView will work after that. I am trying to figure out a way to first expand the path before programmatically selecting the item into view, but no matter what I try, the item does not scroll into view. Is this because the expanding is done on some type of delay?
TreeView creates its visual items (TreeViewItem containers) as lazy as possible. Thus when item has not been expanded its children will not be created. Calling bring into view for container that is not yet created will have no effect.
As you have noticed, expanding item will force its children to be created (in case the virtualization is switched off). However, expanding item programmatically is asynchronous operation, i.e. function call returns but containers are generated at some later point in time.
I would suggest you take a look at this blogpost http://blogs.telerik.com/xamlteam/posts/11-01-12/treeview-bringintoview.aspx . It should work for and fit in your case.
Hristo
the Telerik team
Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

Just so everyone is aware, the method presented by Josh Smith in my post above will not work with the RadTreeView. This is because the items of the tree that are initially collapsed are not actually instantiated, so therefore the selected event will never be registered. To work around this, I used a GalaSoft MVVM messenger event instead, and handled the message in a behavior that brings the item into view. Here is the general code I used.
First, I created a behavior in the View namespace:
public
class
TreeSelectionBehavior : Behavior<FrameworkElement>
{
Messenger messenger = Messenger.Default;
protected
override
void
OnAttached()
{
base
.OnAttached();
messenger.Register<GalaSoft.MvvmLight.Messaging.DialogMessage>(
this
, Identifier, ItemSelected);
}
public
string
Identifier {
get
;
set
; }
public
MyTreeGenericNode SelectedNode
{
get
{
return
(MyTreeGenericNode
)GetValue(SelectedNodeProperty); }
set
{ SetValue(SelectedNodeProperty, value); }
}
// Using a DependencyProperty as the backing store for the selected node object.
public
static
readonly
DependencyProperty SelectedNodeProperty =
DependencyProperty.Register(
"SelectedNode"
,
typeof
(MyTreeGenericNode
),
typeof
(TreeSelectionBehavior),
new
UIPropertyMetadata(
null
));
public
RadTreeView TreeView
{
get
{
return
(RadTreeView)GetValue(TreeViewProperty); }
set
{ SetValue(TreeViewProperty, value); }
}
// Using a DependencyProperty as the backing store for the RadTreeView.
public
static
readonly
DependencyProperty TreeViewProperty =
DependencyProperty.Register(
"TreeView"
,
typeof
(RadTreeView),
typeof
(TreeSelectionBehavior),
new
UIPropertyMetadata(
null
));
public
void
ItemSelected(GalaSoft.MvvmLight.Messaging.DialogMessage dm)
{
Assert.IsNotNull(SelectedNode);
Assert.IsNotNull(TreeView);
TreeView.BringPathIntoView(SelectedNode.DisplayPath);
}
}
The behavior is added to the XAML and bound to the selected item and tree. The reference to i: is for the System.Windows.Interactivity namespace. The reference to v: is for the View namespace:
<
i:Interaction.Behaviors
>
<
v:TreeSelectionBehavior
x:Name
=
"MyTreeSelectionBehavior"
Identifier
=
"TreeSelectionBehavior"
TreeView
=
"{Binding ElementName=MyRadTreeView}"
SelectedNode
=
"{Binding CurrentSelectedItem}"
/>
</
i:Interaction.Behaviors
>
Now, in the view model, I message the behavior when the selection is updated:
CurrentSelectedItem = NodeFoundFromSearch;
GalaSoft.MvvmLight.Messaging.Messenger mes = GalaSoft.MvvmLight.Messaging.Messenger.Default;
mes.Send(
new
GalaSoft.MvvmLight.Messaging.DialogMessage(
"Tree Selection Behavior"
, res =>
{
}),
"TreeSelectionBehavior"
);
Make sure to unregister the message in the cleanup of the view:
messenger.Unregister<GalaSoft.MvvmLight.Messaging.DialogMessage>(MyTreeSelectionBehavior);
One final note - the node class that is used as items source must have a ToString() override that represents the name of the path element for the node:
public
override
string
ToString()
{
return
this
.Name;
}