Home > Software design >  Set isselected properties of TreeViewItem in TreeView WPF, MVVM
Set isselected properties of TreeViewItem in TreeView WPF, MVVM

Time:11-25

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.

treeview wpf code

JobsDTOClass

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.

  • Related