WPF ListBox水平显示并支持滚动

ItemsPanel属性

在WPF中,ListBox提供了一个ItemPanel属性,它可以指定用于控制元素呈现的模板。

对于ListBox,默认使用的是VirtualizingStackPanel.

 

水平显示

我们可以使用ItemsPanel属性来自定义元素显示所使用的面板,继续使用VirtualizingStackPanel,但是将方向控制为水平,并启用水平滚动条,禁用垂直滚动条。

 1 <ListBox  ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Disabled" >
 3     <ListBox.ItemsPanel>
 4         <ItemsPanelTemplate>
 5             <VirtualizingStackPanel Orientation="Horizontal" IsItemsHost="True" />
 6         </ItemsPanelTemplate>
 7     </ListBox.ItemsPanel>
 8 
 9     <ListBoxItem>
10         2343243242
11     </ListBoxItem>
12     <ListBoxItem>
13         2343243242
14     </ListBoxItem>
15     <ListBoxItem>
16         2343243242
17     </ListBoxItem>
18     <ListBoxItem>
19         2343243242
20     </ListBoxItem>
21 </ListBox>

 

运行效果如下:

 

支持滚动

我们可以处理PreviewMouseWheel事件,在事件中,对滚轮的方向和偏移量进行判断,并手动控制滚动

<ListBox  ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Disabled"  PreviewMouseWheel="list_PreviewMouseWheel" >

 

事件处理函数

 1         private void list_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
 2         {
 3             if (sender is ListBox listBox)
 4             {
 5                 var scrollViewer = TreeHelper.FindVisualChild<ScrollViewer>(listBox);
 6                 if (scrollViewer != null)
 7                 {
 8                     scrollViewer.ScrollToHorizontalOffset(scrollViewer.HorizontalOffset - e.Delta);
 9                     e.Handled = true;
10                 }
11             }
12         }

 

这里我们需要查找子元素ScrollViewer,使用了VisualTreeHelper类提供的功能,封装了一个FindVisualChild函数,代码如下

TreeHelper.cs

 1 public class TreeHelper
 2 {
 3     public static T FindVisualChild<T>(DependencyObject dependencyObject) where T : DependencyObject
 4     {
 5         var childrenCount = VisualTreeHelper.GetChildrenCount(dependencyObject);
 6         for (int i = 0; i < childrenCount; i++)
 7         {
 8             DependencyObject child = VisualTreeHelper.GetChild(dependencyObject, i);
 9             if (child is T t)
10             {
11                 return t;
12             }
13             else
14             {
15                 T childOfChild = FindVisualChild<T>(child);
16                 if (childOfChild != null)
17                     return childOfChild;
18             }
19         }
20         return null;
21     }
22 }

 

参考资料:

https://learn.microsoft.com/en-us/dotnet/api/system.windows.controls.itemscontrol.itemspanel?view=windowsdesktop-9.0

posted @ 2025-06-19 11:44  zhaotianff  阅读(240)  评论(0)    收藏  举报