How to programmatically set selected node of a treeview in 1803 version

budding_developer 156 Reputation points
2020-04-03T06:40:34.897+00:00

I am using a treeview in my uwp project which supports 1803 version. I need to know how to set the selected node of the treeview programmatically. Also it would be helpful if solution is provided in C#. Thanks in advance.

Universal Windows Platform (UWP)
0 comments No comments
{count} votes

Accepted answer
  1. Peter Fleischer (former MVP) 19,336 Reputation points
    2020-04-03T09:33:22.67+00:00

    Hi, try following demo:

    XAML:

    <Page
        x:Class="App1.Page06"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:App06"
        xmlns:i="using:Microsoft.Xaml.Interactivity"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
      <Page.DataContext>
        <local:ViewModel/>
      </Page.DataContext>
      <StackPanel>
        <Button Content="Select Node" Command="{Binding Cmd}"/>
        <TreeView SelectionMode="Multiple" Height="400">
          <i:Interaction.Behaviors>
            <local:TvBehavior/>
          </i:Interaction.Behaviors>
        </TreeView>
      </StackPanel>
    </Page>
    

    and code:

    using Microsoft.Xaml.Interactivity;
    using System;
    using System.Windows.Input;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    
    namespace App06
    {
      public class ViewModel
      {
        Random rnd = new Random();
    
        public ICommand Cmd
        {
          get => new RelayCommand((state) =>
          {
            var n = TreeV.RootNodes[rnd.Next(0, TreeV.RootNodes.Count)];
            if (rnd.NextDouble() > .5 && n.HasChildren)
            {
              n.IsExpanded = true;
              n = n.Children[rnd.Next(0, n.Children.Count)];
            }
            //TreeV.SelectedNodes.Clear();
            TreeV.SelectedNodes.Add(n);
          });
        }
    
        public TreeView TreeV { get; set; }
    
            internal void LoadTree()
        {
          for (int i = 1; i < 10; i++)
          {
            var n = new TreeViewNode() { Content = $"Node {i}" };
            TreeV.RootNodes.Add(n);
            for (int k = 1; k < 10; k++) n.Children.Add(new TreeViewNode() { Content = $"SubNode {i} {k}" });
          }
        }
      }
    
      public class TvBehavior : Behavior<TreeView>
      {
        protected override void OnAttached() => AssociatedObject.Loaded += AssociatedObject_Loaded;
        private void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
        {
          var vm = AssociatedObject.DataContext as ViewModel;
          if (vm == null) return;
          vm.TreeV = AssociatedObject;
          vm.LoadTree();
        }
      }
    
      public class RelayCommand : ICommand
      {
        private readonly Predicate<object> _canExecute;
        private readonly Action<object> _execute;
        public event EventHandler CanExecuteChanged;
        public RelayCommand(Action<object> execute) : this(execute, null) { }
        public RelayCommand(Action<object> execute, Predicate<object> canExecute) { _execute = execute; _canExecute = canExecute; }
        public bool CanExecute(object parameter) => (_canExecute == null) ? true : _canExecute(parameter);
        public void Execute(object parameter) => _execute(parameter);
        public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
      }
    }
    

1 additional answer

Sort by: Most helpful
  1. Richard Zhang-MSFT 6,936 Reputation points
    2020-04-03T08:17:29.847+00:00

    Hello,​

    Welcome to our Microsoft Q&A platform!

    We can usually set TreeView's selected item by binding.

    This is a simple idea:

    1. Create a data class, which contains a property to control whether it is selected

    public class Model : INotifyPropertyChanged
    {
        public string Name { get; set; }
        public bool _isSelected;
        public bool IsSelected
        {
            get => _isSelected;
            set
            {
                _isSelected = value;
                OnPropertyChanged();
            }
        }
        public List<Model> Children { get; set; }
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged([CallerMemberName]string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    

    2. Create a data collection as a data source

    private ObservableCollection<SupportTopic> TopicCollection = new ObservableCollection<SupportTopic>();
    

    3. Create the corresponding DataTemplate and bind the corresponding properties

    <TreeView x:Name="MyTreeView"
          ItemsSource="{x:Bind TopicCollection}">
        <TreeView.ItemTemplate>
            <DataTemplate x:DataType="local:Model">
                <TreeViewItem Content="{x:Bind Name}"
                              ItemsSource="{x:Bind Children}"
                              IsSelected="{x:Bind IsSelected,Mode=OneWay}"
                              />
            </DataTemplate>
        </TreeView.ItemTemplate>
    </TreeView>
    

    In this case, if you need to set an item in the list as a selected item, you only need to set the corresponding Model.IsSelected to True.

    Thanks.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.