2017-11-13 15 views
0

私はリスト内の一番上の項目にスクロールするScrollIntoViewを使用して、」(デフォルトでは常に一番下のものにスクロールしていますが、一部の指定された場合には、私はこれに他の方法が必要です)WPFのscrollIntoView奇妙な行動

だから、最初のアイテムがリストに追加され、次にScrollIntoView(Items[0])が呼び出されます。 ScrollIntoViewはDispatcher.BeginInvokeの内部で呼び出されているため、UIスレッド内にあります。

一般的な考え方は、項目の「短い」説明で初期リストを見てから、そのうちの1つを選択し、「短い」部分も含むすべての情報を見るということです。

すなわち:

1)

enter image description here

2)

enter image description here

私はケース1の要素1をクリックしてるときに、私が期待してい写真2を参照してください。しかし時々私は参照してください

enter image description here

たとえば、カーソルがリストボックスにとどまっていると、ビューが常に正しく更新されていることがわかりました。私は "AddItem"と "ScrollTop"メソッドの呼び出しスタックをチェックしました。それらは正しい順序であり、 "ScrollTop"は常に適切に呼び出されます。

他のすべてのケース(アイテム2またはアイテム0をピックアップしているとき)では、「ScrollTop」がうまく機能します。

だから私はWPFの最適化のようなものだと思います。 1)の項目1の情報はケース2の場合と同じ場所にあるためです。 WPFは毎回ビューを更新するわけではありません。

リストボックスをスクロールした後に毎回更新する方法はありますか?

私はUpdateLayout()で試しました。それは助けになりませんでした。

UPDATE(コード例): メインスレッドコード:

UIManager.AddListItem(item1); 
UIManager.AddListItem(item2); 
UIManager.AddListItem(item3); 
UIManager.ScrollToTop(); 

UIManagerの実装:

public void AddListItem(ListItem item) 
{ 
ExecuteUI(() => 
{ 
    MyList.AddItem(item); 
}); 
} 

public void ScrollToTop() 
{ 
ExecuteUI(() => 
{ 
    MyList.ScrollToTop(); 
}); 
} 

MyListModel実装:

public void AddItem(ListItem item) 
{ 
lock (linesLock) 
{ 
    if (Lines == null) 
    Lines = new ObservableCollection<ItemModel>(); 

    ItemModel line = new ItemModel(item); 
    Lines.Add(line); //When line added it automatically scrolls to it 
    // via ((INotifyCollectionChanged)ListLines.Items).CollectionChanged += LinesChanged;  
} 
} 

public void ScrollToTop() 
{ 
    if (Lines.Count == 0 || ScrollEvent == null) 
      return; 
    ScrollEvent(this, new ScrollEventArgs(Lines[0])); 
    // via Model.ScrollEvent += ScrollEvent; 
} 

モデルXAMLコード:

// ListLines is a ListBox 

private void LinesChanged(object sender, NotifyCollectionChangedEventArgs e) 
{ 
     ListLines.ScrollIntoView(e.NewItems[0]); 
} 

private void ScrollEvent(object sender, ScrollEventArgs e) 
{ 
    ListLines.ScrollIntoView(e.Item); 
} 

答えて

0

ScrollToVerticalOffsetまたはScrollViewerScrollToTop方法を使用してください:

public void Click(object sender, RoutedEventArgs e) 
{ 
    ScrollViewer sv = GetChildOfType<ScrollViewer>(listBox); 
    if (sv != null) 
     sv.ScrollToVerticalOffset(0); 
} 

public static T GetChildOfType<T>(DependencyObject depObj) where T : DependencyObject 
{ 
    if (depObj == null) 
     return null; 

    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++) 
    { 
     var child = VisualTreeHelper.GetChild(depObj, i); 

     var result = (child as T) ?? GetChildOfType<T>(child); 
     if (result != null) 
      return result; 
    } 
    return null; 
} 

をしかし、また、常に質問をするとき、あなたの問題のMinimal, Complete, and Verifiable exampleを提供することを忘れないでください。

+0

残念ながら、これは私が説明したのと同じ結果をもたらします。コード例を追加しました。 – Ksice