WPF 重写 ListBox 内 ItemTemplate 时 WrapPanel 不会自动换行与出现滚动条的 BUG
参考
- 豆包
- https://cloud.tencent.com/developer/ask/sof/1193734
- https://cloud.tencent.com/developer/article/2107404
- https://bbs.csdn.net/topics/395825750
- https://blog.csdn.net/qq_39427511/article/details/130616277
- https://www.dovov.com/wpf-61.html
- https://cloud.tencent.com/developer/ask/sof/121491
- https://blog.csdn.net/yangwenxue1989/article/details/81624240
- https://zhuanlan.zhihu.com/p/489417698
- https://www.cnblogs.com/mqxs/p/5640809.html
- https://stackoverflow.org.cn/questions/19589663
环境
| 软件/系统 | 版本 | 说明 | 
|---|---|---|
| Windows | windows 10 专业版 22H2 64 位操作系统, 基于 x64 的处理器 | |
| Microsoft Visual Studio | Community 2022 (64 位) - Current 版本 17.13.6 | |
| .NET Framework | 4.8 | 
问题
问题梳理可能不太清晰,具体参考代码
- 样式定义有先后顺序,需要先定义再引用,否则找不到
- 非 UI线程更新UI需要通过Application.Current.Dispatcher.Invoke
- ListBox可以设置- ItemContainerStyle、- DataTemplate,其中- ItemContainerStyle是元素的容器,如果设置了- ControlTemplate,需要使用- <ContentPresenter />显示内容元素;- DataTemplate是元素项的内容
- 通过 ItemsPanel修改ListBox的模板,这样就可以去掉隐藏的ScrollViewer元素(ScrollViewer元素默认比ListBox窄2像素,就会导致内容如果宽度和父元素一致,则会出现滚动条)
- <UniformGrid Columns="4" />可以指定几列自动换行
- ListBox宽度没有固定,如果不固定那么- WrapPanel就不会自动换行
- 若 ListBox未显式设置Width(默认值为Auto),则WrapPanel绑定ListBox.Width会绑定到NaN(无效值),导致WrapPanel宽度由内容决定,可能无法正确换行。显式设置ListBox.Width或使用ActualWidth替代Width(处理动态宽度场景)
- ListBox的默认模板中,- ScrollViewer的内容区域(- Viewport)可能存在隐含的布局逻辑。即使- ListBox的- BorderThickness设为- 0,- ScrollViewer的内部计算可能仍会保留极细微的空间(如像素舍入误差或默认样式残留),导致- WrapPanel的实际可用宽度略小于- ListBox.ActualWidth。- {Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type ScrollViewer}}, Path=ActualWidth}
- 自定义 ListBox的ItemsPanel后,给ListBox包一个ScrollViewer即可正常显示滚动条
预览

代码
- MainWindow.xaml<Window x:Class="WPFWallpaper.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:WPFWallpaper" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:vm="clr-namespace:WPFWallpaper.ViewModel" Title="WPFWallpaper" Width="800" Height="450" mc:Ignorable="d"> <Window.DataContext> <vm:MainWindowVM /> </Window.DataContext> <DockPanel> <Menu Style="{StaticResource MenuStyle}"> <MenuItem Command="{Binding SelectFolderCommand}" Header="选择文件夹" /> <MenuItem Header="关于" /> </Menu> <StatusBar DockPanel.Dock="Bottom"> <TextBlock Text="状态" /> </StatusBar> <ScrollViewer VerticalScrollBarVisibility="Auto"> <ListBox ItemsSource="{Binding ImageModels}" Style="{StaticResource ListStyle}" /> </ScrollViewer> </DockPanel> </Window>
- MainWindowStyle.xaml<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:model="clr-namespace:WPFWallpaper.Model"> <!-- 菜单栏 --> <Style x:Key="MenuStyle" TargetType="{x:Type Menu}"> <Setter Property="Height" Value="20" /> <Setter Property="DockPanel.Dock" Value="Top" /> </Style> <!-- 列表外观样式 --> <Style x:Key="ListItemBoxStyle" TargetType="{x:Type ListBoxItem}"> <Setter Property="Width" Value="190" /> <!-- 如果不需要默认的列表外观样式,可以重写模板 --> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ListBoxItem}"> <ContentPresenter /> </ControlTemplate> </Setter.Value> </Setter> </Style> <!-- 项样式 --> <Style x:Key="ImageStyle" TargetType="{x:Type Image}"> <Setter Property="Stretch" Value="Fill" /> <Setter Property="Source" Value="{Binding FilePath}" /> </Style> <DataTemplate x:Key="ListItemTemplate" DataType="{x:Type model:ImageModel}"> <StackPanel Margin="10,0,10,10" HorizontalAlignment="Center" VerticalAlignment="Center"> <Image Source="{Binding FilePath}" Stretch="Fill" /> <Button Content="选择" /> </StackPanel> </DataTemplate> <!-- 列表 --> <Style x:Key="ListStyle" TargetType="{x:Type ListBox}"> <Setter Property="ScrollViewer.HorizontalAlignment" Value="Stretch" /> <Setter Property="Margin" Value="0" /> <Setter Property="Padding" Value="0" /> <!-- Setter Property="Width" Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type DockPanel}}, Path=Width}" / --> <Setter Property="BorderBrush" Value="Transparent" /> <Setter Property="BorderThickness" Value="0" /> <Setter Property="HorizontalAlignment" Value="Left" /> <Setter Property="VerticalAlignment" Value="Top" /> <Setter Property="ItemContainerStyle" Value="{StaticResource ListItemBoxStyle}" /> <Setter Property="ItemTemplate" Value="{StaticResource ListItemTemplate}" /> <Setter Property="ItemsPanel"> <Setter.Value> <ItemsPanelTemplate> <!-- WrapPanel Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type ListBox}}, Path=ActualWidth}" Margin="0" Orientation="Horizontal" / --> <WrapPanel Margin="0" Orientation="Horizontal" /> </ItemsPanelTemplate> </Setter.Value> </Setter> <Setter Property="Template"> <Setter.Value> <ControlTemplate> <ItemsPresenter /> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary>
    博  主 :夏秋初
地 址 :https://www.cnblogs.com/xiaqiuchu/p/18896250
 
如果对你有帮助,可以点一下 推荐 或者 关注 吗?会让我的分享变得更有动力~
转载时请带上原文链接,谢谢。
    
地 址 :https://www.cnblogs.com/xiaqiuchu/p/18896250
如果对你有帮助,可以点一下 推荐 或者 关注 吗?会让我的分享变得更有动力~
转载时请带上原文链接,谢谢。
 
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号