2013-03-23 9 views
6

Chcę, aby użytkownik mógł wyszukiwać elementy w TreeView. Po wprowadzeniu wyszukiwanego tekstu należy przewinąć widok TreeViewItem do widoku.TreeView BringIntoView z MVVM

W tej chwili używam wzoru MVVM dla TreeView, dla TreeViewItems i MainView.

Co muszę zrobić, aby uzyskać funkcjonalność BringIntoView wykorzystującą MVVM? Czy jest jakaś własność, którą mogę związać? (w MFC było coś takiego jak FirstVisibileItem)

Widziałem "rozwiązanie" z zachowaniem. Czy to naprawdę konieczne?

+0

myślę MVVM powinien zatrzymać się na koncepcji "wybrany". Jeśli to nie spowoduje przewinięcia elementu do widoku, będę używał zwykłych zdarzeń w widoku. –

+1

Masz rację, viewmodel nie powinien przejmować się widokiem. Ale tutaj jest jakiś szczególny przypadek, który, jak sądzę, jest "na granicach" MVVM. –

+0

Maszyna wirtualna powinna wskazywać określony element, ale to wszystko. Problemy z przewijaniem są lepiej rozwiązywane w widoku. –

Odpowiedz

5

Problem można rozwiązać za pomocą zachowania.

Ten CodeProject article opisuje to bardzo dobrze i działa po wyjęciu z pudełka.

8

Zgodnie z wymienionym artykułem Code Project, oto przykład kodu, który pokazuje, jak skonfigurować zachowanie i jak zintegrować zachowanie w XAML.

Konfiguracja zachowanie:

/// <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 
} 

Następnie zintegrować TreeViewItemBehavior w XAML:

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

Miłej zabawy :-)

+0

Setter dla właściwości dependency nie jest stosowany do elementów w moim widoku drzewa dopóki nie stają się widoczne poprzez ich rozszerzenie. Dlatego TreeViewItem.Selected nie ma początkowo dołączonego zdarzenia. Jeśli mam kod, który programowo rozszerza węzły i wybiera jedną głębię w drzewie, nie jest wyświetlany. – DannyMeister

+0

Znalazłem rozwiązanie dla mojej konkretnej sprawy. Jeśli włączona jest właściwość zależności, to miałem sens, aby przejść dalej i przewinąć do elementu, jeśli został już wybrany. Wewnątrz znaku if, po linii: 'item.Selected + = OnTreeViewItemSelected;' Dodałem: 'if (item.IsSelected) {item.RaiseEvent (new RoutedEventArgs (TreeViewItem.SelectedEvent)); } ' – DannyMeister

+0

To nie jest zachowanie, to rozszerzenie. TreeViewItem * Zachowanie * – Snicker