2009-07-11 124 views
2

我試圖在WPF中實現MVVM模式。我跟着傑里米阿勒斯的Very simple MVVM demo application。我有一個具有綁定到一個ObservableCollection一個ListBox:列表框滾動條不按照選定的項目(與ICollectionView)

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

我增加了一個ICollectionView對列表框管理選定的項目。它還允許我有兩個按鈕,允許我選擇列表中的上一個和下一個項目。

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

這一切的偉大工程,但是,當選擇的產品列表框的顯示區域的下方,列表框的滾動條沒有相應的移動。

如何將ListBox的滾動條/顯示區域與所選項目同步?

回答

6

我找到了答案。 我需要使用

myListBoxItem.BringIntoView(); 

的問題是,我並沒有想添加任何代碼隱藏,因爲我實現MVVM。

解決方案使用的是附加行爲。約什史密斯有一個偉大的文章:Introduction to Attached Behaviors in WPF

我adedd一個二傳手在ListBox中的項目的風格:

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

,並添加下面的類(只改的TreeView從Josh的文章列表框):

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 
} 

它的工作原理!