2009-06-23 36 views
36

WPF listviewで円滑なスクロールを実装することは、Firefoxでの動作と同様ですか?
Firefoxのブラウザにlistviewの項目がすべて含まれていて、マウスの中央ボタン(リリースではない)を押したままドラッグすると、listviewの項目がスムーズにスクロールされます。あなたが解放するとき、それは止まるべきです。WPFリストビューで円滑なスクロールを実装することはできますか?

winformsではこれができないようですが、WPFで利用できるかどうか疑問に思っていますか?

答えて

64

あなたはスムーズなスクロールを実現することができますが、アイテムの仮想化を失うので、基本的にこの手法を使用する必要がありますが、リスト内のいくつかの要素を持っている場合のみ:

情報ここに:Smooth scrolling on listbox

を、あなたは試してみました設定:リストボックスの

ScrollViewer.CanContentScroll="False" 

このようにして、スクロールはlistBoxではなくパネルで処理されます。ただし、仮想化を失うと、仮想化が失われますが、コンテンツをたくさん持っていると遅くなる可能性があります。

+1

ありがとうございます。仮想化とは何ですか? –

+10

VirtualizationStackPanel(ListBoxなどのデフォルトのItemsPanel)内のコンテンツは、アイテムが表示されるまで/実際にアイテムのレイアウトをレンダリングしません。したがって、多数の視覚的に複雑なアイテムでは、一度にわずかなパーセンテージでしかUIを生成しないため、大幅なパフォーマンスの向上を実現できます。 詳細情報: http://msdn.microsoft.com/en-us/library/system.windows.controls.virtualizingstackpanel.aspx – rmoore

+1

これは、論理的なスクロールから物理的なスクロールに切り替えることです(あなたが実装しているStackPanelを使用していると仮定します)。 IScrollInfo)。論理スクロールをしたいがスムーズにしたい場合は、これは役に立ちません – Schneider

3

のListViewScrollViewer.CanContentScroll添付プロパティを設定してみてください。しかし、Pop Catalinのように、アイテムの仮想化が失われると、リスト内のすべてのアイテムが表示される必要がなくなったときではなく、一度に読み込まれて読み込まれます。リストが巨大な場合、メモリとパフォーマンスの問題。

+0

ありがとう。私は、ええ、それは大丈夫だろうと思う。しかし、このプロパティをfalseに設定すると、どのようにスクロールを実装しますか?途中でクリック+ドラッグしたように、スムーズにスクロールダウンしたいまたは、この機能は既に組み込まれていますが、このプロパティで有効になっていますか? –

+0

プロパティによって自動的に有効化されます。私は中ボタンのスクロール機能についてはわかりませんが、リストはまだスクロールする必要があります。 CanContentScrollの名前はちょっと誤解されています。私はそれを二重チェックしようとします。 – Eddie

+0

ありがとうございます。名前:うん、確かに奇妙な名前。プロパティが有効になっているときのこのスクロールは、スクロールバーで正しく動作します。 –

10

あなたが求めていることを実際に行うことは可能ですが、かなりの量のカスタムコードが必要になります。

通常、WPFでは、ScrollViewerは論理スクロールと呼ばれるものを使用します。これは、オフセット量ではなくアイテム単位でスクロールすることを意味します。その他の答えは、論理スクロールの動作を物理スクロールの動作に変更できるいくつかの方法をカバーしています。もう1つの方法は、ScrollViwerとIScrollInfoの両方で公開されるScrollToVertialOffsetメソッドとScrollToHorizo​​ntalOffsetメソッドを使用することです。

大きな部分を実装するには、マウスホイールを押したときにスクロールして、MouseDownおよびMouseMoveイベントを使用する必要があります。 MouseDownで

<ListView x:Name="uiListView" 
      Mouse.MouseDown="OnListViewMouseDown" 
      Mouse.MouseMove="OnListViewMouseMove" 
      ScrollViewer.CanContentScroll="False"> 
    .... 
</ListView> 

、我々は我々がスクロールどの方向を決定するために相対的な点として使用する現在のマウス位置を記録しようとしている。マウスの動きで、我々はScrollViwer成分を得ようとしていますそれに応じてスクロールします。

private Point myMousePlacementPoint; 

private void OnListViewMouseDown(object sender, MouseButtonEventArgs e) 
{ 
    if (e.MiddleButton == MouseButtonState.Pressed) 
    { 
     myMousePlacementPoint = this.PointToScreen(Mouse.GetPosition(this)); 
    } 
} 

private void OnListViewMouseMove(object sender, MouseEventArgs e) 
{ 
    ScrollViewer scrollViewer = ScrollHelper.GetScrollViewer(uiListView) as ScrollViewer; 

    if (e.MiddleButton == MouseButtonState.Pressed) 
    { 
     var currentPoint = this.PointToScreen(Mouse.GetPosition(this)); 

     if (currentPoint.Y < myMousePlacementPoint.Y) 
     { 
      scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset - 3); 
     } 
     else if (currentPoint.Y > myMousePlacementPoint.Y) 
     { 
      scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset + 3); 
     } 

     if (currentPoint.X < myMousePlacementPoint.X) 
     { 
      scrollViewer.ScrollToHorizontalOffset(scrollViewer.HorizontalOffset - 3); 
     } 
     else if (currentPoint.X > myMousePlacementPoint.X) 
     { 
      scrollViewer.ScrollToHorizontalOffset(scrollViewer.HorizontalOffset + 3); 
     } 
    } 
} 

public static DependencyObject GetScrollViewer(DependencyObject o) 
{ 
    // Return the DependencyObject if it is a ScrollViewer 
    if (o is ScrollViewer) 
    { return o; } 

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

     var result = GetScrollViewer(child); 
     if (result == null) 
     { 
      continue; 
     } 
     else 
     { 
      return result; 
     } 
    } 
    return null; 
} 

それがコンセプトのちょうど証拠だが、それは間違いなくあなたが正しい方向に始める必要があるとして、それが欠けているいくつかのエリアがあります。マウスが最初のMouseDownポイントから離れると、それを常にスクロールさせるには、スクロール・ロジックをDispatcherTimerまたは類似のものに入れることができます。

0

リストビューの高さをautoに設定し、スクロールビューアでラップしてみてください。

<ScrollViewer IsTabStop="True" VerticalScrollBarVisibility="Auto"> 
    <ListView></ListView> 
</ScrollViewer> 

このことができますScrollViewerの 希望の高さを言及するのを忘れないでください....

+0

リストビューに大量のデータがある場合、これは機能しません –

1

(あなたがビットをハックして喜んでいる場合または4.0)は、.NET 4.5を使用している場合はそこです答えはover hereです。

関連する問題