当方向=水平时,是什么让我的 VirtualizingStackPanel 无法虚拟化?

问题描述 投票:0回答:1

我有一个

ListView
,我尝试用它来模拟 Windows 资源管理器的“列表”视图。为了显示项目,我使用 S. Baeumlisberger
VirtualizingWrapPanel
,它可以水平滚动并很好地虚拟化其项目。

但是,在某些时候,用户会希望对项目进行分组(例如按文件类型)。这就是事情变得棘手的地方。分组时,

ListView
使用
<GroupStyle.Panel>
显示多个
VirtualizingWrapPanel
,每组项目一个。

对于这个

<GroupStyle.Panel>
,我使用
VirtualizingStackPanel
,并将其
Orientation
设置为
Horizontal
,因为我希望组水平显示,就像在Windows资源管理器中一样。这可行,但它不会虚拟化它的项目(而当我将其设置为
Vertical
时它会虚拟化)。

这是我的 XAML:

<ListView x:Name="PART_ListView" SelectionMode="Extended" 
            FocusVisualStyle="{x:Null}" ScrollViewer.IsDeferredScrollingEnabled="False" 
            ScrollViewer.CanContentScroll="True" BorderThickness="0" 
            Grid.IsSharedSizeScope="True" VirtualizingPanel.ScrollUnit="Pixel" 
            VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.IsVirtualizingWhenGrouping="True"
            VirtualizingPanel.VirtualizationMode="Recycling" VirtualizingPanel.CacheLength="2" 
            VirtualizingPanel.CacheLengthUnit="Page">
    <ListView.Resources>
        <GroupStyle x:Key="groupStyle">
            <GroupStyle.Panel>
                <ItemsPanelTemplate>
                    <VirtualizingStackPanel Orientation="Horizontal" />
                </ItemsPanelTemplate>
            </GroupStyle.Panel>
            <GroupStyle.ContainerStyle>
                <Style TargetType="{x:Type GroupItem}">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate>
                                <Expander Margin="0,0,20,0" IsExpanded="True" Style="{DynamicResource lailaShell_GroupByExpanderStyle}">
                                    <Expander.Resources>
                                        <converters:ListViewGroupingHeightConverter x:Key="listViewGroupingHeightConverter" />
                                    </Expander.Resources>
                                    <Expander.Header>
                                        <StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch" x:Name="expanderHeader">
                                            <TextBlock Text="{Binding Name}" Foreground="DarkBlue" VerticalAlignment="Center" />
                                        </StackPanel>
                                    </Expander.Header>
                                    <ItemsPresenter Margin="5,0,0,0">
                                        <ItemsPresenter.Height>
                                            <MultiBinding Converter="{StaticResource listViewGroupingHeightConverter}">
                                                <Binding Path="." ElementName="expanderHeader" />
                                                <Binding Path="ActualHeight" ElementName="PART_ListView" />
                                            </MultiBinding>
                                        </ItemsPresenter.Height>
                                    </ItemsPresenter>
                                </Expander>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </GroupStyle.ContainerStyle>
        </GroupStyle>
    </ListView.Resources>
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <vwp:VirtualizingWrapPanel SpacingMode="None">
                <vwp:VirtualizingWrapPanel.Style>
                    <Style>
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding Path=Items.GroupDescriptions.Count, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListView}}}" Value="0">
                                <Setter Property="vwp:VirtualizingWrapPanel.Margin" Value="20,0,0,0" />
                            </DataTrigger>
                            <DataTrigger Binding="{Binding Path=Items.GroupDescriptions.Count, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListView}}}" Value="1">
                                <Setter Property="vwp:VirtualizingWrapPanel.Margin" Value="0,0,0,0" />
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </vwp:VirtualizingWrapPanel.Style>
            </vwp:VirtualizingWrapPanel>
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
    <i:Interaction.Behaviors>
        <behaviors:SelectionBehavior />
    </i:Interaction.Behaviors>
    <ListView.ItemTemplate>
        <DataTemplate>
            <Border>
                <Grid>
                    <Grid.ColumnDefinitions >
                        <ColumnDefinition Width="16" />
                        <ColumnDefinition Width="4" />
                        <ColumnDefinition Width="16" />
                        <ColumnDefinition Width="4" />
                        <ColumnDefinition Width="Auto" SharedSizeGroup="A" />
                    </Grid.ColumnDefinitions>
                    <Image Source="{Binding PropertiesByKeyAsText[e77e90df-6271-4f5b-834f-2dd1f245dda4:2].FirstIcon16Async, IsAsync=True}"
                            Width="14" Height="16">
                        <Image.Style>
                            <Style>
                                <Setter Property="Image.Visibility" Value="Collapsed" />
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding PropertiesByKeyAsText[e77e90df-6271-4f5b-834f-2dd1f245dda4:2].HasIcon}" Value="True">
                                        <Setter Property="Image.Visibility" Value="Visible" />
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </Image.Style>
                    </Image>
                    <Image Grid.Column="2" Source="{Binding IconAsync[16], IsAsync=True}" Width="16" Height="16" 
                            UseLayoutRounding="True" SnapsToDevicePixels="True">
                        <Image.Style>
                            <Style>
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding IsHidden}" Value="True">
                                        <Setter Property="Image.Opacity" Value="0.5" />
                                    </DataTrigger>
                                    <DataTrigger Binding="{Binding IsCut}" Value="True">
                                        <Setter Property="Image.Opacity" Value="0.5" />
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </Image.Style>
                    </Image>
                    <Image Grid.Column="2" Source="{Binding OverlayImageAsync, IsAsync=True}" Width="16" Height="16" 
                            UseLayoutRounding="True" SnapsToDevicePixels="True"
                            VerticalAlignment="Bottom" HorizontalAlignment="Left">
                        <Image.Style>
                            <Style>
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding IsHidden}" Value="True">
                                        <Setter Property="Image.Opacity" Value="0.5" />
                                    </DataTrigger>
                                    <DataTrigger Binding="{Binding IsCut}" Value="True">
                                        <Setter Property="Image.Opacity" Value="0.5" />
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </Image.Style>
                    </Image>
                    <TextBlock Grid.Column="4" MaxWidth="200"
                                Text="{Binding DisplayName}" TextTrimming="CharacterEllipsis">
                        <TextBlock.Style>
                            <Style>
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding IsCompressed}" Value="True">
                                        <Setter Property="TextBlock.Foreground" Value="Blue" />
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </TextBlock.Style>
                    </TextBlock>
                </Grid>
            </Border>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

如果您感兴趣,可以在 https://sourceforge.net/p/laila-shell/code/ci/master/tree/ 找到完整的源代码。

wpf vb.net xaml .net-core
1个回答
0
投票

我终于成功了!现在是凌晨 2 点 44 分,我们还要再忙两周 :-P

我不知道为什么,但我开始遇到麻烦,

VirtualizingWrapPanel
不断闪烁,直到它变得无法使用,当我破坏程序时,我在堆栈跟踪中看到它不断测量和排列。所以我认为它很难坚持恒定的项目大小,因此我将
ItemSize
VirtualizingWrapPanel
属性设置为恒定值。现在突然间我所有的问题都消失了,一切都正常了:

<ListView.ItemsPanel>
    <ItemsPanelTemplate>
        <vwp:VirtualizingWrapPanel SpacingMode="None" Orientation="Vertical" ItemSize="240,20">
        </vwp:VirtualizingWrapPanel>
    </ItemsPanelTemplate>
</ListView.ItemsPanel>
© www.soinside.com 2019 - 2024. All rights reserved.