現在、最初のWPFプロジェクトに取り組んでおり、リストビューをスクロール可能にしようとしています。最初は、リストビューの幅と高さを制限して、コンテンツがスペースを超えるたびにスクロールバーを自動的に表示することで簡単にできると考えました。これは最初は問題ないように見えましたが、処理されたPreviewMouseDown-Event(リストのアイテムをドラッグできるようにする)により、アイテムを選択した後は機能しません。
2回目の試行(ScrollViewerを使用)
<ScrollViewer>
<ListView ItemsSource="{Binding FileViewModels}"
PreviewMouseDown="ListView_MouseMove"
Height="450" Width="200"/>
</ScrollViewer>
もちろん、これにより、リストのコンテンツが最大の高さより大きくなると、2番目のスクロールバーが表示されます。また、アイテムを選択した後でも、バーをドラッグしても機能しませんでした。
番目(かなりばかげている)試行(スクロールバーの複製を無効にする)
<ScrollViewer>
<ListView ItemsSource="{Binding FileViewModels}"
PreviewMouseDown="ListView_MouseMove"
Height="450" Width="200"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"/>
</ScrollViewer>
これにより、スクロールバーの複製が削除され、マウスホイールによるスクロールが有効になりましたが、スクロールバーが無効になったため、クリックしてドラッグしても移動できませんでした。
4回目の試行(ScrollViewerの一定サイズ)
<ScrollViewer Height="450" Width="200">
<ListView ItemsSource="{Binding FileViewModels}"
PreviewMouseDown="ListView_MouseMove"/>
</ScrollViewer>
ListViewから幅/高さの制約を削除し、ScrollViewerに移動しました。これにより、スクロールバーが有効になり、重複が削除されます。残念ながら、マウスホイールはもう機能しません(スクロールバーをドラッグすると正常に機能します)。
誰かがマウスホイールがもう機能しない理由とこれを修正する方法を説明してもらえますか?
編集たぶん最初の解決策に戻る必要があります。明らかに、ListViewのテンプレートには既にScrollViewerが含まれています。残っている問題は、PreviewMouseDownイベントが処理されているため、アイテムを選択した後にスクロールバーをドラッグできないことです(その場合、マウスホイールによるスクロールは引き続き機能します)。アイテムのドラッグを別の方法で処理する必要があります(スクロールバーを追加する前にうまく機能しました)。または、カーソルがスクロールバーの上にあるかどうかを検出する方法はありますか(スクロールを有効にするアイテムを選択解除できます)?または、他の提案はありますか?
これが役立つ場合があります。
private void ListViewScrollViewer_PreviewMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
{
ScrollViewer scv = (ScrollViewer)sender;
scv.ScrollToVerticalOffset(scv.VerticalOffset - e.Delta);
e.Handled = true;
}
これはおそらく最も快適なソリューションでしょう。
<ListView.Template>
<ControlTemplate>
<ScrollViewer>
<ItemsPresenter></ItemsPresenter>
</ScrollViewer>
</ControlTemplate>
</ListView.Template>
<ScrollViewer Background="Transparent">
Backgroundがnullの場合、マウスホイールはScrollViewerで機能しません。背景を透明または他の値に設定できます。
私の場合 :
<ScrollViewer ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Auto" >
<DataGrid x:Name="dataGrid" SelectionMode="Single" ItemsSource="{Binding}" SelectedValuePath="{Binding Item}" AutoGenerateColumns="True">
</DataGrid>
</ScrollViewer>
デザインは、外側のスコープ、つまりScrollViewerのVerticalScrollBarVisibility属性を無効にしました
私にとってこれはうまくいきました:
<ListView.Template>
<ControlTemplate>
<!-- Empty template to allow ScrollViewer to capture mouse scroll -->
<ItemsPresenter />
</ControlTemplate>
</ListView.Template>
これの代わりに:
<ListView.Template>
<ControlTemplate>
<ScrollViewer>
<ItemsPresenter></ItemsPresenter>
</ScrollViewer>
</ControlTemplate>
</ListView.Template>
Rockyが提供したソリューションにコメントを追加したいと思います。私にとってはうまくいきましたが、後でグリッドをスクロールするために別のウィンドウで使用する必要がありました。私は問題に直面しました:scrollviewerは下端までスクロールしませんでした。理由は、無効なVerticalOffset値を設定しようとしたためです。以下のコードは私のためにうまく機能します(PreviewMouseWheelハンドラーを変更するだけです:
private void UIElement_OnPreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
ScrollViewer scroll = (ScrollViewer)sender;
if (e.Delta < 0)
{
if (scroll.VerticalOffset - e.Delta <= scroll.ExtentHeight - scroll.ViewportHeight)
{
scroll.ScrollToVerticalOffset(scroll.VerticalOffset - e.Delta);
}
else
{
scroll.ScrollToBottom();
}
}
else
{
if (scroll.VerticalOffset + e.Delta > 0)
{
scroll.ScrollToVerticalOffset(scroll.VerticalOffset - e.Delta);
}
else
{
scroll.ScrollToTop();
}
}
e.Handled = true;
}