i am a newbie to WPF mvvm, i created a treeview and i want to set isSelected value of a specific treeviewitem in this tree (for example, item with "19-ASDFDSSD") but i dont know how to do it. Can you help me? Any help will be appreciated.
CodePudding user response:
TreeView.SelectedItem
is read only, so a value can't be pushed from the ViewModel.
The way I've handled this is via the use of a Behavior
class.
1 - Create a base class for TreeView item data, that includes IsSelected and IsExpanded properties.
public class perTreeViewItemViewModelBase : perViewModelBase
{
private bool _isSelected;
public bool IsSelected
{
get => _isSelected;
set => Set(nameof(IsSelected), ref _isSelected, value);
}
private bool _isExpanded;
public bool IsExpanded
{
get => _isSelected;
set => Set(nameof(IsExpanded), ref _isExpanded, value);
}
...
}
2 - Create a helper class for TreeView controls to implement the behavior, with a BoundSelectedItem
attached property.
public class perTreeViewHelper : Behavior<TreeView>
{
public object BoundSelectedItem
{
get => GetValue(BoundSelectedItemProperty);
set => SetValue(BoundSelectedItemProperty, value);
}
public static readonly DependencyProperty BoundSelectedItemProperty =
DependencyProperty.Register("BoundSelectedItem",
typeof(object),
typeof(perTreeViewHelper),
new FrameworkPropertyMetadata(null,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
OnBoundSelectedItemChanged));
private static void OnBoundSelectedItemChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
if (args.NewValue is perTreeViewItemViewModelBase item)
{
item.IsSelected = true;
}
}
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.SelectedItemChanged = OnTreeViewSelectedItemChanged;
}
protected override void OnDetaching()
{
AssociatedObject.SelectedItemChanged -= OnTreeViewSelectedItemChanged;
base.OnDetaching();
}
private void OnTreeViewSelectedItemChanged(object obj, RoutedPropertyChangedEventArgs<object> args)
{
BoundSelectedItem = args.NewValue;
}
}
3 - Create styles for TreeViewItem and TreeView to bind the IsSelected property of the perTreeViewItemViewModelBase instance to the corresponding TreeViewItem property
<Style x:Key="perTreeViewItemContainerStyle" TargetType="{x:Type TreeViewItem}">
<!-- Link the properties of perTreeViewItemViewModelBase to the corresponding ones on the TreeViewItem -->
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
...
</Style>
<Style TargetType="{x:Type TreeView}">
<Setter Property="ItemContainerStyle" Value="{StaticResource perTreeViewItemContainerStyle}" />
</Style>
4 - In the View, use the behavior class to bind the BoundSelectedItem attached proprety to a corresponding property in the ViewModel
<TreeView ItemsSource="{Binding ...}">
<i:Interaction.Behaviors>
<vhelp:perTreeViewHelper BoundSelectedItem="{Binding SelectedItem}" />
</i:Interaction.Behaviors>
For more details on my take on how to handle TreeView controls in a MVVM context (including check boxes for item selection and lazy loading of item data), check out my blog post.