2009-07-11 5 views
2

WPF에서 MVVM 패턴을 구현하려고합니다. 나는 Jeremy Alles의 Very simple MVVM demo application을 따라 갔다.목록 상자 스크롤바가 선택한 항목 (ICollectionView 포함)을 따르지 않습니다.

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

내가 목록 상자에서 선택한 항목을 관리하는 ICollectionView에 추가 : 나는 ObservableCollection에 바인딩이있는 목록 상자가 있습니다. 또한 목록에서 이전 및 다음 항목을 선택할 수있는 두 개의 단추가 있습니다. 선택한 항목이 목록 상자의 표시 영역 아래에있을 때

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

이 모든 것은, 그러나, 목록 상자의 스크롤바 따라 큰 이동하지 않습니다 작동합니다.

목록 상자의 스크롤 막대/표시 영역을 선택한 항목과 어떻게 동기화 할 수 있습니까?

답변

6

답변을 찾았습니다. 나는

myListBoxItem.BringIntoView(); 

문제는 내가 MVVM을 구현하고 같이 코드 숨김 추가하고 싶어하지 않았다이었다 사용하는 데 필요한.

해결책은 첨부 된 동작을 사용하고 있습니다. Josh Smith는 이에 대한 훌륭한 기사를 가지고 있습니다 : Introduction to Attached Behaviors in WPF.

내가 목록 상자에있는 항목의 스타일에 세터를 adedd : 그것은 작동

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 
} 

:

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

다음과 같은 클래스를 추가 (만 목록 상자에 조쉬의 기사에서 트 리뷰 변경) !! !!

관련 문제