I have an sfTreeView control bound to a collection of objects, each of which has a property SubtreeIsSelected. That property is true if the particular element/node, or any of its child elements/nodes, is selected. Here is the XAML:
<sf:SfTreeView Grid.Column="1" Grid.Row="0"
Grid.ColumnSpan="2"
Margin="5"
ItemsSource="{Binding RootCategories}"
NotificationSubscriptionMode="CollectionChange"
ChildPropertyName="ChildNodes">
<sf:SfTreeView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Margin="5"
VerticalAlignment="Center"
IsChecked="{Binding IsSelected}"/>
<TextBlock Margin="5"
VerticalAlignment="Center"
Text="{Binding DisplayName}"/>
</StackPanel>
</DataTemplate>
</sf:SfTreeView.ItemTemplate>
<sf:SfTreeView.HierarchyPropertyDescriptors>
<tve:HierarchyPropertyDescriptor IsExpandedPropertyName="SubtreeIsSelected"/>
</sf:SfTreeView.HierarchyPropertyDescriptors>
</sf:SfTreeView>
Unfortunately, this XAML does not result in the various nodes that I know are selected (and which have SubtreeIsSelected set to true) from opening up.
What might I be doing wrong?
|
<sf:SfTreeView Grid.Column="1" Grid.Row="0"
Grid.ColumnSpan="2"
Margin="5"
ItemsSource="{Binding ImageNodeInfo}"
NotificationSubscriptionMode="CollectionChange"
ChildPropertyName="SubFiles">
<sf:SfTreeView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Margin="5"
VerticalAlignment="Center"
IsChecked="{Binding IsSelected}"/>
<TextBlock Margin="5"
VerticalAlignment="Center"
Text="{Binding ItemName}"/>
</StackPanel>
</DataTemplate>
</sf:SfTreeView.ItemTemplate>
<sf:SfTreeView.HierarchyPropertyDescriptors>
<tve:HierarchyPropertyDescriptor ChildPropertyName="SubFiles"
TargetType="local:FileManager"
IsExpandedPropertyName="SubtreeIsSelected"/>
</sf:SfTreeView.HierarchyPropertyDescriptors>
</sf:SfTreeView> |
Thanx, that was very helpful. FYI, it might be worth updating the online documentation so it indicates the TargetType field is required. It's not obvious why it needs to be set, and, as you pointed out, it's critical.
One other follow-up question...
I'm seeing behavior that makes me think the IsExpandedPropertyName binding is not dynamic. Meaning the target property (SubtreeIsSelected in your example) only gets read when the collection the node is a part of is changed.
I say this because the root of my hierarchical node collection expands when I modify the IsExpandedPropertyNames source property (in my viewmodel) at runtime...but only because I rebuild the collection. The child collections (e.g., the nodes down the tree from a root node) do not get rebuilt and don't get updated.
Is that observation correct? If so, would it be possible to make the source property pointed to by IsExpandedPropertyName get read whenever the source value changes? That would be helpful because it wouldn't require rebuilding the entire tree every time a node gets selected and you want its parent nodes to expand.
Some additional info...
Here's the code I'm using to try and get all of the parent nodes above selected nodes to expand:
public bool IsSelected
{
get => _isSelected;
set
{
SetProperty( ref _isSelected, value );
SelectableNode<TKey, TEntity>? curNode = (SelectableNode<TKey, TEntity>)this;
do
{
curNode.OnPropertyChanged(nameof(SubtreeHasSelectedItems));
curNode = (SelectableNode<TKey, TEntity>?)curNode.ParentNode;
} while (curNode != null);
}
}
public bool SubtreeHasSelectedItems
{
get => DescendantsAndSelf.Any( x => x.IsSelected );
}
While I realize this may be a bit hard to follow, SubtreeHasSelectedItems is the property I tie to IsExpandedPropertyName. It's true whenever any node in the hierarchy is selected or has a descendant node that is selected.
Whenever IsSelected is updated the tree is walked back to the root and for every node along that path a PropertyChanged event is raised for the node's SubtreeHasSelectedItems property. Which should cause all the nodes along that path to open up.
Only it doesn't. Only the root opens up, as you can see in the following picture (I haven't included it, but all the children of the node labeled Auto has IsSelected as true, so Auto should be expanded).
Success!! (for now :)).
The problem appears to have been that I was using the default NodePopulationMode, OnDemand. Consequently, when I set the expansion flag on the the lower level nodes they didn't exist yet, and so the expansion flag got ignored.