2009-07-11 7 views
2

Ich versuche, das MVVM-Muster in WPF zu implementieren. Ich bin Jeremy Alles's Very simple MVVM demo application gefolgt. Ich habe eine ListBox, die eine Bindung an ein ObservableCollection hat:ListBox Bildlaufleiste folgt nicht ausgewählten Element (mit ICollectionView)

<ListBox 
    Name="myListBox" 
    IsSynchronizedWithCurrentItem="True" 
    ItemsSource="{Binding Persons}"> 
    <ListBox.ItemTemplate> 
     <DataTemplate> 
      <views:PersonsView /> 
     </DataTemplate> 
    </ListBox.ItemTemplate> 
</ListBox> 

Ich habe ein ICollectionView das ausgewählte Element auf der List-Box zu verwalten. Es erlaubt mir auch, zwei Knöpfe zu haben, mit denen ich die vorherigen und nächsten Einträge in der Liste auswählen kann.

private void GoToPrevious() 
{ 
    this.collectionView.MoveCurrentToPrevious(); 
} 
private void GoToNext() 
{ 
    this.collectionView.MoveCurrentToNext(); 
} 

alles funktionieren großartig, aber wenn das ausgewählte Element unter dem angezeigten Bereich des listbox ist, werden die Listbox der Scrollbar nicht entsprechend bewegen.

Wie kann ich die Bildlaufleiste/den Anzeigebereich der ListBox mit dem ausgewählten Element synchronisieren?

Antwort

6

Ich habe die Antwort gefunden. Ich brauchte

myListBoxItem.BringIntoView(); 

Das Problem war, zu benutzen, dass ich nicht Code-behind hinzuzufügen haben wollte, da ich MVVM bin der Umsetzung.

Die Lösung verwendet Attached Behaviors. Josh Smith hat einen tollen Artikel dazu: Introduction to Attached Behaviors in WPF.

ich einen Setter auf den Stil der Elemente in der ListBox adedd:

<ListBox.ItemContainerStyle> 
    <Style TargetType="{x:Type ListBoxItem}"> 
     <Setter 
      Property="custom:ListBoxItemBehavior.IsBroughtIntoViewWhenSelected" 
      Value="True" /> 
    </Style> 
</ListBox.ItemContainerStyle> 

Und hinzugefügt, um die folgende Klasse (nur geänderte TreeView von Joshs Artikel zu ListBox):

public static class ListBoxItemBehavior 
{ 
    #region IsBroughtIntoViewWhenSelected 

    public static bool GetIsBroughtIntoViewWhenSelected(ListBoxItem listBoxItem) 
    { 
     return (bool)listBoxItem.GetValue(IsBroughtIntoViewWhenSelectedProperty); 
    } 

    public static void SetIsBroughtIntoViewWhenSelected(
     ListBoxItem listBoxItem, bool value) 
    { 
     listBoxItem.SetValue(IsBroughtIntoViewWhenSelectedProperty, value); 
    } 

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

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

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

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

    static void OnListBoxItemSelected(object sender, RoutedEventArgs e) 
    { 
     // Only react to the Selected event raised by the ListBoxItem 
     // 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; 

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

    #endregion // IsBroughtIntoViewWhenSelected 
} 

Es funktioniert !!

Verwandte Themen