Filtering tree and maintaining selected nodes.

6 posts, 0 answers
  1. Michael Fooks
    Michael Fooks avatar
    17 posts
    Member since:
    Dec 2009

    Posted 22 Jan 2010 Link to this post

    I have a "search" box that allows a user to filter the tree based on the underlying entity lable name using a filter on the collectionview. This works great except that it collapses all the tree nodes and doesn't maintain their expanded state. Is there a way to filter and maintian tree node state?
  2. Valentin.Stoychev
    Admin
    Valentin.Stoychev avatar
    2198 posts

    Posted 22 Jan 2010 Link to this post

    Hi Bronwen Zande,

    You need to two-way bind the IsSelected property of the RadTreeViewItem to a property of the business object if you want the selection to be kept.

    Let us know if you need help on this.

    Kind regards,
    Valentin.Stoychev
    the Telerik team

    Instantly find answers to your questions on the new Telerik Support Portal.
    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
  3. UI for WPF is Visual Studio 2017 Ready
  4. Michael Fooks
    Michael Fooks avatar
    17 posts
    Member since:
    Dec 2009

    Posted 24 Jan 2010 Link to this post

    I dont think IsSelected is the correct property as I can have more than one branch open. I thought it'd be IsExpanded? I tried binding to IsExpanded which works great until my filter excludes that branch and then it sets IsExpanded to false and then when i remove my filter the branch is collasped.

    So I apply the following style to a treeview:

     

     

     

     

    <Style x:Key="TreeItemContainerStyle" TargetType="telerikNavigation:RadTreeViewItem">

     

     

     

     

    <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"/>

     

     

     

     

    </Style>

    -- fwtree is just our class that inherits telerik tree

     

     

     

     

    <controls:FwTreeView ItemsSource="{Binding Path=DataSource}"

     

     

     

     

    KeyboardNavigation.DirectionalNavigation="Contained"

     

     

     

     

    BorderBrush="Transparent"

     

     

     

     

    Background="Transparent"

     

     

     

     

    ItemContainerStyle="{StaticResource TreeItemContainerStyle}"

     

     

     

     

    ItemTemplate="{DynamicResource itemTemplate}"

     

     

     

    Selected="FwTreeView_Selected" IsLineEnabled="True" x:Name="fwTree"

     

     

     

     

    >

     

     

     

     

     

     

     

     

     

    </controls:FwTreeView>

    and apply the following code to filter the tree when the user changes the filter text:

     

     

     

    private void FilterDataSource()

     

    {

     

     

    if (DataSource != null && DataSource.Count > 0)

     

    {

    SetFilter(FilteredDataSource);

    }

    }

     

     

    private void SetFilter(ICollectionView source)

     

    {

    source.Filter =

     

    delegate(object obj)

     

    {

     

     

    var item = obj as MenuEntity;

     

     

     

    if (item == null) return false;

     

     

     

    if (item.MenuType == MenuType.FunctionItem)

     

    {

     

     

    return string.IsNullOrEmpty(Filter) || item.Label.ToLower().Contains(Filter);

     

    }

     

     

    if (item.MenuItems != null && item.MenuItems.Count > 0)

     

    {

     

     

    ICollectionView itemsCollectionView;

     

     

     

    if (_views.ContainsKey(item.Id.ToString()))

     

    {

    itemsCollectionView = _views[item.Id.ToString()];

    }

     

     

    else

     

     

     

     

     

    {

    itemsCollectionView =

     

    CollectionViewSource.GetDefaultView(item.MenuItems);

     

    _views.Add(item.Id.ToString(), itemsCollectionView);

    }

    SetFilter(itemsCollectionView);

     

     

    return !itemsCollectionView.IsEmpty;

     

    }

     

     

    return string.IsNullOrEmpty(Filter);

     

    };

    }

     

     

  5. Kiril Stanoev
    Admin
    Kiril Stanoev avatar
    1511 posts

    Posted 27 Jan 2010 Link to this post

    Hello Bronwen,

    I have created a project that demonstrates a similar scenario. In such scenarios the key is, if you are going to remove a parent(due to filter conditions), then do not filter its children. Have a look at the attached project for further reference and let me know if you have additional questions on the matter.

    All the best,
    Kiril Stanoev
    the Telerik team

    Instantly find answers to your questions on the new Telerik Support Portal.
    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
  6. Michael Fooks
    Michael Fooks avatar
    17 posts
    Member since:
    Dec 2009

    Posted 27 Jan 2010 Link to this post

    Thanks for that. In your example if you change Flanders to Simpson and apply/unapply the filter you lose the  the expanded state.

    I need to filter children and if there's no nodes, filter the branches aswell.  Would like ot maintain the expanded states in the underlying object so when the filter is cleared I wanted to show the tree as it was before.
  7. Valentin.Stoychev
    Admin
    Valentin.Stoychev avatar
    2198 posts

    Posted 02 Feb 2010 Link to this post

    Hi Bronwen Zande,

    Unfortunately the TreeViewItem is setting the IsExpanded to False internally, when the children are cleared. This is done in order to update its Expanded visual state.

    When this is done the model is also updated and the IsExpanded state is lost at this very moment.

    To deal with this we can use a copy of the collection which we can only use when filtering. When we unfilter we can use again the original collection. Here is the modified code behind:


    public partial class Window1 : Window
    {
        Families families = new Families();
        Families familiesCopy = new Families();
        public Window1()
        {
            InitializeComponent();
            treeView1.ItemsSource = families;
        }
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            treeView1.Items.Filter = delegate(object obj)
            {
                if (obj is Family)
                {
                    Family family = obj as Family;
                    if (family.Name.Equals("Flanders"))
                    {
                        ICollectionView view = CollectionViewSource.GetDefaultView(family.Members);
                        view.Filter = m => (m as Member).Name.Equals("Homer");
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                return false;
            };
        }
        private void UnButton_Click(object sender, RoutedEventArgs e)
        {
            treeView1.Items.Filter = null;
              
            foreach (Family family in familiesCopy)
            {
                CollectionViewSource.GetDefaultView(family.Members).Filter = null;
            }
            treeView1.ItemsSource = families;
        }
    }

    Sincerely yours,
    Valentin.Stoychev
    the Telerik team

    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
    Follow the status of features or bugs in PITS and vote for them to affect their priority.
Back to Top
UI for WPF is Visual Studio 2017 Ready