gpt4 book ai didi

wpf - 扩展器、网格和列表框 = 无虚拟化

转载 作者:行者123 更新时间:2023-12-01 12:34:55 25 4
gpt4 key购买 nike

我有一个列表框,在一个网格内,在一个扩展器内。 ListBox 绑定(bind)到 IList。

当我第一次展开 Expander 控件时,ListBox 会处理 IList 中的所有项目(可能是数千个),而不是只处理屏幕上可见的项目。

但是,如果我修复了 ListBox 控件的高度,它将按预期运行,并且仅访问 IList 中可见的那些项目。

实际上,虚拟化不起作用,尽管我认为这与 ListBox 在准备内容项时无法确定高度有关。

XAML 基本上如下(为简化起见,删除了一些内容)...

<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Expander ExpandDirection="Right"
Grid.Column="0"
Grid.Row="0"
Grid.RowSpan="2"
Header="Documents"
IsExpanded="False">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition Height="50" />
</Grid.RowDefinitions>
</Grid>
<ListBox Name="listBox"
Grid.Row="1"
ItemsSource="{Binding Path=Items}"
SelectedIndex="{Binding Path=SelectedIndex}"
SelectedItem="{Binding Path=SelectedItem}"
SelectionMode="Single"
Width="250">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<TextBlock Grid.Column="0"
Style="{StaticResource prompt}">
<TextBlock.Text>
<MultiBinding StringFormat="{}{0}{1:00000}">
<Binding Path="..."
FallbackValue="0" />
<Binding Path="..." />
</MultiBinding>
</TextBlock.Text></TextBlock>
<TextBlock Grid.Column="1"
Style="{StaticResource prompt}">
<TextBlock.Text>
<Binding Path="ItemCount"
StringFormat="{}{0} Items"
FallbackValue="" />
</TextBlock.Text></TextBlock>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Expander>
<v:DocumentView x:Name="documentView"
Grid.Column="1"
Grid.Row="0"
DocumentID="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type v:BatchView}}, Path=ViewModel.SelectedItem.ID}"
IsActive="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type v:BatchView}}, Path=IsActive}" />
<StackPanel Grid.Column="1"
Grid.Row="1"
Style="{StaticResource buttonStackStyle}">
<Button Command="{Binding Path=PreviousCommand}"
Style="{StaticResource previousButtonStyle}" />
<Button Command="{Binding Path=NextCommand}"
Style="{StaticResource nextButtonStyle}" />
</StackPanel>
</Grid>

任何人都可以建议我如何将 ListBox 的高度设置为 Grid.Row 父级的 ActualHeight 吗?或者,有人可以提供更好的解决方案吗?

谢谢。

最佳答案

短版:删除 Grid.RowSpan从扩展器。

长版:

背景: (大体上)

当您定义 RowDefinition 的高度时可能会发生三件事,具体取决于您最终使用的单位类型:

  • 像素 - 放置在该行中的任何 UIElement 都会将定义的行高传递给 MeasureArrange元素的方法。
  • 自动 - 网格将通过无穷大作为 Measure 的高度然后 element.DesiredSize.Height对于 Arrange .
  • Star - 网格将考虑所有行的高度,单位为像素和自动;计算从其可用高度剩下的高度,然后除以为所有行定义的“星星总数”——这是一颗星星的高度;然后,根据其星形定义的乘数分配每个行高;这个高度被传递给 MeasureArrange方法。

  • 相同的逻辑仅适用于关于宽度而不是高度的列定义。

    因此,星形定义是“停止”元素,像素定义也是“停止”,但它可以在渲染 View 之外,自动定义是“让”元素成为它想要的任何大小。

    所有这些逻辑都是递归的,所以你需要从两个方向思考(下面的解释)。

    在你的情况下

    在一个方向。 ListBox是在一个星排,所以它会被停止。父网格也停止了(因为扩展器的模板使用 DockPanel 这也是一个“停止面板”)。扩展器被定义为从星形行开始,但它跨越到自动行 - 这意味着它将被允许在高度上增长'直到无穷大。糟糕……是时候逆转了。

    现在反方向。扩展器没有停止,子网格没有停止(因为网格假设它有无限的高度可用),因此列表框没有停止, ScrollViewer在列表框的模板中没有停止所以它是 ViewportHeight是无限的,对于 VirtualizingStackPanel排列项目(并且是滚动查看器的子项)这意味着所有项目都在 View 中==渲染所有元素。

    对于具有默认模板的 WPF 窗口,您始终可以假定窗口正在停止其子元素。因此,如果删除行跨度定义没有解决问题,请继续向上遍历,直到找到另一个没有停止其子高度的元素并更改其定义或更改面板以阻止高度从增长到无穷大(滚动查看器因创建这些行为,尤其是那些隐藏在模板中的行为)。

    关于wpf - 扩展器、网格和列表框 = 无虚拟化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6800918/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com