Search code examples
treeviewwinrt-xaml-toolkit

WinRT XAML Toolkit TreeView Save state


there is a way to save the state of a treeview (expanded and selected properties) in order to keep state during navigation and tombstone of application?

I don't want to add such of information on itemsource since semantically are two different metter. ItemSource is a domain object not having any relationship with expanded state.

Thank you.


Solution

  • You can save those informations inside the ViewModel associated with each node of the tree like this :

    public class PersonViewModel
    {
        readonly List<Person> _children = new List<Person>();
        private bool _isExpanded;
    
        public IList<Person> Children
        {
            get { return _children; }
        }
    
        public string Name { get; set; }
    
        /// <summary>
        /// Gets/sets whether the TreeViewItem 
        /// associated with this object is expanded.
        /// </summary>
        public bool IsExpanded
        {
            get { return _isExpanded; }
            set
            {
                if (value != _isExpanded)
                {
                    _isExpanded = value;
                    this.OnPropertyChanged("IsExpanded");
                }            
            }
        }
    }
    

    Then you can bind those properties with the View.

    <TreeView ItemsSource="{Binding Persons}">
        <TreeView.ItemContainerStyle>
            <Style TargetType="{x:Type PersonViewModel}">
            <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
            <Style.Triggers>
                <Trigger Property="IsSelected" Value="True">
                    <Setter Property="FontWeight" Value="Bold" />
                </Trigger>
            </Style.Triggers>
            </Style>
        </TreeView.ItemContainerStyle>
    
        <TreeView.Resources>
            <HierarchicalDataTemplate DataType="{x:Type local:PersonViewModel}" 
                                      ItemsSource="{Binding Children}">
                <StackPanel>
                    <TextBlock Text="{Binding Name}" />
                </StackPanel>
            </HierarchicalDataTemplate>
    
            <DataTemplate DataType="{x:Type local:PersonViewModel}">
                <StackPanel>                
                    <TextBlock Text="{Binding Name}" />
                </StackPanel>
            </DataTemplate>
        </TreeView.Resources>
    </TreeView>
    

    http://www.codeproject.com/Articles/26288/Simplifying-the-WPF-TreeView-by-Using-the-ViewMode


    But what you are looking for :

    You probably want to separate the navigation from the menu with the use of a ContentPresenter so you don't need to save the state of the menu.

    <Page 
        x:Class="DataCloner.Uwp.Shell"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:DataCloner.Uwp"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:views="using:DataCloner.Uwp.Views"
        mc:Ignorable="d">
    
        <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
            <Grid.RowDefinitions>
                <RowDefinition Height="auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Grid>
                <views:TopBarView/>
            </Grid>
            <SplitView x:Name="rootSplitView" Content="{Binding myContentView}" DisplayMode="Inline" IsPaneOpen="True" Grid.Row="1"
                    OpenPaneLength="300">
                <SplitView.Pane>
                    <views:MenuPanelView/>
                </SplitView.Pane>                
            </SplitView>
        </Grid>
    </Page>