C# WPF:在高度属性设置为“自动”的 ListView 中防止水平滚动条覆盖最后一项
Posted
技术标签:
【中文标题】C# WPF:在高度属性设置为“自动”的 ListView 中防止水平滚动条覆盖最后一项【英文标题】:C# WPF: prevent last item cover by horizontal scrollbar in ListView with Height property set to "Auto" 【发布时间】:2011-05-29 17:18:41 【问题描述】:我在 StackPanel 中有一个 WPF ListView,Height="Auto"。它能做我想做的事真是太好了——根据 ListView 中包含的所有项目来改变它的高度。我的 ListView 上也有 HorizontalScrollBarVisiblity="Auto",这符合我的需要。
当我的 ListView 的列的整个宽度大于 ListView 控件的宽度时会出现问题(即用户减小窗口和此控件的宽度)。在那种情况下,显然会出现水平滚动条 - 没关系。问题是这个滚动条覆盖了 ListView 项目的最后一个(底部)项目,因此它部分不可见。
没有出现垂直滚动条,这没关系 - 我不想要它。我只想正确计算我的 ListView 高度,因此它会考虑显示的水平滚动条的高度并将其包含在计算中,以便所有项目都完全可见。
Xaml 代码示例:
<ListView Name="lvProcedures" ItemsSource="Binding Path=Procedures" SelectionMode="Single">
<ListView.View>
<GridView AllowsColumnReorder="False" ColumnHeaderToolTip="Lista zabiegów">
<GridViewColumn DisplayMemberBinding="Binding Path=procedure" Header="A" Width="150" />
<GridViewColumn DisplayMemberBinding="Binding Path=location" Header="B" Width="100" />
<GridViewColumn DisplayMemberBinding="Binding Path=material" Header="C" Width="180" />
<GridViewColumn DisplayMemberBinding="Binding Path=other" Header="D" Width="180" />
<GridViewColumn DisplayMemberBinding="Binding Path=description" Header="E" Width="400" />
</GridView>
</ListView.View>
</ListView>
我现在想创建覆盖 MeasureOverride 的用户控件(可能只有 ListView 的派生类??),但我认为这不是解决如此小但令人恼火的“错误”的好方法,而且它仍然让我难以实施解决方案。
有人可以为这个问题提供一些优雅的解决方案吗? 任何想法将不胜感激。
【问题讨论】:
通常情况下是这样的。 Horizontal ScrollViewer 将出现在最后一个 ListViewItem 下方。您正在谈论的问题只会在 ListView 的高度因任何原因受到限制时才会发生,例如明确设置高度 【参考方案1】:@bartivo:我没有得到和你一样的结果——底部的水平滚动条似乎没有遮挡最低的项目。我想知道您是否为 ListView 和 ScrollViewer 使用自定义 ControlTemplate,b/c 默认的 ScrollViewer 模板有两行,第一行中的 ScrollContentPresenter (Height="*") 和第二行中的 HorizontalScrollBar (Height= "Auto") 从而确保一个不会与另一个重叠。
也许您可以尝试为您的 ListView 和 ScrollViewer 使用这些样式,看看是否仍然存在该问题:
<SolidColorBrush x:Key="ListBorder" Color="#828790"/>
<Style x:Key="x:Static GridView.GridViewScrollViewerStyleKey" TargetType="x:Type ScrollViewer">
<Setter Property="Focusable" Value="false"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="x:Type ScrollViewer">
<Grid SnapsToDevicePixels="true" Background="TemplateBinding Background">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DockPanel Margin="TemplateBinding Padding">
<ScrollViewer Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" DockPanel.Dock="Top">
<GridViewHeaderRowPresenter Margin="2,0,2,0" SnapsToDevicePixels="TemplateBinding SnapsToDevicePixels" AllowsColumnReorder="Binding TemplatedParent.View.AllowsColumnReorder, RelativeSource=RelativeSource TemplatedParent" ColumnHeaderContainerStyle="Binding TemplatedParent.View.ColumnHeaderContainerStyle, RelativeSource=RelativeSource TemplatedParent" ColumnHeaderContextMenu="Binding TemplatedParent.View.ColumnHeaderContextMenu, RelativeSource=RelativeSource TemplatedParent" ColumnHeaderStringFormat="Binding TemplatedParent.View.ColumnHeaderStringFormat, RelativeSource=RelativeSource TemplatedParent" ColumnHeaderTemplate="Binding TemplatedParent.View.ColumnHeaderTemplate, RelativeSource=RelativeSource TemplatedParent" ColumnHeaderTemplateSelector="Binding TemplatedParent.View.ColumnHeaderTemplateSelector, RelativeSource=RelativeSource TemplatedParent" ColumnHeaderToolTip="Binding TemplatedParent.View.ColumnHeaderToolTip, RelativeSource=RelativeSource TemplatedParent" Columns="Binding TemplatedParent.View.Columns, RelativeSource=RelativeSource TemplatedParent"/>
</ScrollViewer>
<ScrollContentPresenter x:Name="PART_ScrollContentPresenter" SnapsToDevicePixels="TemplateBinding SnapsToDevicePixels" KeyboardNavigation.DirectionalNavigation="Local" Content="TemplateBinding Content" ContentTemplate="TemplateBinding ContentTemplate" CanContentScroll="TemplateBinding CanContentScroll"/>
</DockPanel>
<ScrollBar x:Name="PART_HorizontalScrollBar" Cursor="Arrow" Visibility="TemplateBinding ComputedHorizontalScrollBarVisibility" Grid.Row="1" Maximum="TemplateBinding ScrollableWidth" Minimum="0.0" Value="Binding HorizontalOffset, Mode=OneWay, RelativeSource=RelativeSource TemplatedParent" Orientation="Horizontal" ViewportSize="TemplateBinding ViewportWidth"/>
<ScrollBar x:Name="PART_VerticalScrollBar" Cursor="Arrow" Visibility="TemplateBinding ComputedVerticalScrollBarVisibility" Grid.Column="1" Maximum="TemplateBinding ScrollableHeight" Minimum="0.0" Value="Binding VerticalOffset, Mode=OneWay, RelativeSource=RelativeSource TemplatedParent" Orientation="Vertical" ViewportSize="TemplateBinding ViewportHeight"/>
<DockPanel Background="Binding Background, ElementName=PART_VerticalScrollBar" Grid.Column="1" Grid.Row="1" LastChildFill="false">
<Rectangle Fill="White" Width="1" Visibility="TemplateBinding ComputedVerticalScrollBarVisibility" DockPanel.Dock="Left"/>
<Rectangle Fill="White" Height="1" Visibility="TemplateBinding ComputedHorizontalScrollBarVisibility" DockPanel.Dock="Top"/>
</DockPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ListViewStyle1" TargetType="x:Type ListView">
<Setter Property="Background" Value="DynamicResource x:Static SystemColors.WindowBrushKey"/>
<Setter Property="BorderBrush" Value="StaticResource ListBorder"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Foreground" Value="#FF042271"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="x:Type ListView">
<Microsoft_Windows_Themes:ListBoxChrome x:Name="Bd" SnapsToDevicePixels="true" Background="TemplateBinding Background" BorderBrush="TemplateBinding BorderBrush" BorderThickness="TemplateBinding BorderThickness" RenderFocused="TemplateBinding IsKeyboardFocusWithin" RenderMouseOver="TemplateBinding IsMouseOver">
<ScrollViewer Style="DynamicResource x:Static GridView.GridViewScrollViewerStyleKey" Padding="TemplateBinding Padding">
<ItemsPresenter SnapsToDevicePixels="TemplateBinding SnapsToDevicePixels"/>
</ScrollViewer>
</Microsoft_Windows_Themes:ListBoxChrome>
<ControlTemplate.Triggers>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" TargetName="Bd" Value="DynamicResource x:Static SystemColors.ControlBrushKey"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
【讨论】:
Meleak 和softwarequestioneer - 你是完全正确的......我只是忘记了我使用了我自己的控件样式和模板呃,在这样一个简单的问题上浪费了几个小时。我现在已经修复了我的模板,一切都是正确的!谢谢你的回答! +1,我会投票,因为 bartivo 不能:) 很高兴你解决了!以上是关于C# WPF:在高度属性设置为“自动”的 ListView 中防止水平滚动条覆盖最后一项的主要内容,如果未能解决你的问题,请参考以下文章