Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TreeView BringIntoView with MVVM

I want the user to be able to search for Items in a TreeView. After entering a searchtext the TreeViewItem should be scrolled into view.

Right now I am using the MVVM Pattern for the TreeView, for the TreeViewItems and the MainView.

What do I have to do to get the functionality of BringIntoView utilizing MVVM? Is there some property I can bind? (in MFC there was something like FirstVisibileItem)

Have seen a "solution" with a behavior. Is it really necessary?

like image 333
Mare Infinitus Avatar asked Mar 23 '13 12:03

Mare Infinitus


2 Answers

According to the mentioned Code Project article, here is the Code example that shows how to setup the Behavior and how to integrate the Behavior in XAML.

Setup the behavior:

/// <summary>
/// Exposes attached behaviors that can be
/// applied to TreeViewItem objects.
/// </summary>
public static class TreeViewItemBehavior
{
    #region IsBroughtIntoViewWhenSelected
    public static bool GetIsBroughtIntoViewWhenSelected(TreeViewItem treeViewItem)
    {
        return (bool)treeViewItem.GetValue(IsBroughtIntoViewWhenSelectedProperty);
    }

    public static void SetIsBroughtIntoViewWhenSelected(      TreeViewItem treeViewItem, bool value)
   {
       treeViewItem.SetValue(IsBroughtIntoViewWhenSelectedProperty, value);
   }

   public static readonly DependencyProperty IsBroughtIntoViewWhenSelectedProperty =
    DependencyProperty.RegisterAttached(
    "IsBroughtIntoViewWhenSelected",
    typeof(bool),
    typeof(TreeViewItemBehavior),
    new UIPropertyMetadata(false, OnIsBroughtIntoViewWhenSelectedChanged));

    static void OnIsBroughtIntoViewWhenSelectedChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e)
    {
        TreeViewItem item = depObj as TreeViewItem;
        if (item == null)
           return;

        if (e.NewValue is bool == false)
           return;

        if ((bool)e.NewValue)
           item.Selected += OnTreeViewItemSelected;
        else
           item.Selected -= OnTreeViewItemSelected;
    }

    static void OnTreeViewItemSelected(object sender, RoutedEventArgs e)
    {
       // Only react to the Selected event raised by the TreeViewItem
       // whose IsSelected property was modified. Ignore all ancestors
       // who are merely reporting that a descendant's Selected fired.
       if (!Object.ReferenceEquals(sender, e.OriginalSource))
         return;

       TreeViewItem item = e.OriginalSource as TreeViewItem;
       if (item != null)
          item.BringIntoView();
    }

    #endregion // IsBroughtIntoViewWhenSelected
}

Then integrate the TreeViewItemBehavior in XAML:

<TreeView.ItemContainerStyle>
  <Style TargetType="{x:Type TreeViewItem}">
    <Setter Property="local:TreeViewItemBehavior.IsBroughtIntoViewWhenSelected" Value="True"/>
  </Style>
</TreeView.ItemContainerStyle>

Have fun :-)

like image 185
kbisang Avatar answered Nov 04 '22 06:11

kbisang


The problem can be solved with an Behavior.

This CodeProject article describes it very good and it works out of the box.

like image 26
Mare Infinitus Avatar answered Nov 04 '22 07:11

Mare Infinitus