0

更新信息好的,抱歉,我不得不检查我的问题和标题。但是,尽管我们进行了多次测试,但问题的缩小范围并不容易追踪。您会在下面找到导致无法解释的错误的新代码,以及由于遗留原因而留下的旧版本问题。这个问题很容易重现。

更新代码 绑定Listview到 anObservableCollection并用大量项目填充它,在我们的例子中超过 30k 左右。最终结果是,当您增加项目数量时,ItemsStackPanel中的ListView扩展超出包含网格。它发生在 的两个方向上,ItemsStackPanel但当方向设置为 时更容易发生Horizontal

我们的问题是如何解决这个问题,即在不丢失虚拟化的情况下避免流出包含网格?

请注意,我们需要处理如此多的文件,因为我们正在构建一个照片应用程序,在该应用程序中通常要显示数以万计的图像/视频。除了这个错误,UWP 应用实际上在所有问题上都对此做出了很好的响应。

谢谢

XAML

    <Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>

    <Grid Grid.Row="1" Background="LightGreen">
        <ListView
          ItemsSource="{x:Bind Items}"
          ScrollViewer.HorizontalScrollMode="Enabled"
          ScrollViewer.HorizontalScrollBarVisibility="Visible" HorizontalAlignment="Left">
            <ListView.ItemsPanel>
                <ItemsPanelTemplate>
                    <ItemsStackPanel Orientation="Horizontal"/>
                </ItemsPanelTemplate>
            </ListView.ItemsPanel>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="Not working"/>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</Grid>

C#

    public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
        Items = new ObservableCollection<string>();
        for (int i = 0; i < 30000; i++)//Increase length here
        {
            Items.Add($"Item 1");
        }
    }
    public ObservableCollection<string> Items { get; }
}

旧代码(跳过它)

以下代码显示 2 ListView,只有一个区别:

第一个 ListView 将 绑定ItemsSourceCollectionViewSource.View源设置为 a 的 a FileInformationFactory。下面的 UI 显示了一个按钮,可以选择 100 多张图片来填充它ListView(请参阅编辑部分)。

第二个 ListView 将 绑定ItemsSource到另一个CollectionViewSource.View,其源设置为 trivial ObservableCollection

结果

ItemsStackPanel只要' 的方向设置为,第一个 ListView 就会超出网格容器Horizontal。切换 ItemsSource 并没有解决这个问题,因此表明这个问题是特定于FileInformationFactory.GetVirtualizedFilesVector()方法的。

在此处输入图像描述

问题

如何在不丢失虚拟化的情况下解决这个问题?

谢谢

XAML

    <Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="auto"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <StackPanel Grid.ColumnSpan="1" Orientation="Horizontal">
        <AppBarButton Icon="Folder"
                      LabelPosition="Collapsed"
                      Click="FolderPickerButton_Click"/>
    </StackPanel>
    <Grid Grid.Row="1" Background="LightGreen">
        <ListView
              ItemsSource="{x:Bind CollectionViewSource.View, Mode=OneWay}"
              ScrollViewer.HorizontalScrollMode="Enabled"
              ScrollViewer.HorizontalScrollBarVisibility="Visible" HorizontalAlignment="Left">
            <ListView.ItemsPanel>
                <ItemsPanelTemplate>
                    <ItemsStackPanel Orientation="Horizontal"/>
                </ItemsPanelTemplate>
            </ListView.ItemsPanel>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="Not working" TextWrapping="WrapWholeWords"/>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
    <Grid Grid.Row="2" Background="Yellow">
        <ListView
              ItemsSource="{x:Bind WorksCollectionViewSource.View, Mode=OneWay}"
              ScrollViewer.HorizontalScrollMode="Enabled"
              ScrollViewer.HorizontalScrollBarVisibility="Visible" HorizontalAlignment="Left">
            <ListView.ItemsPanel>
                <ItemsPanelTemplate>
                    <ItemsStackPanel Orientation="Horizontal"/>
                </ItemsPanelTemplate>
            </ListView.ItemsPanel>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="Working" TextWrapping="WrapWholeWords"/>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</Grid>

C#

    public sealed partial class Scenario5 : Page
{
    public Scenario5()
    {
        this.InitializeComponent();
        Items = new ObservableCollection<string>();
        for (int i = 0; i < 30000; i++)
        {
            Items.Add($"Item 1");
        }
        CollectionViewSource = new CollectionViewSource();
        WorksCollectionViewSource = new CollectionViewSource();
    }

    private StorageFolder _folder;
    private QueryOptions _queryOptions;
    private StorageFileQueryResult _query;
    private FileInformationFactory _fileInformationFactory;

    public CollectionViewSource CollectionViewSource { get; set; }

    public CollectionViewSource WorksCollectionViewSource { get; set; }

    public ObservableCollection<string> Items { get; }

    private async void FolderPickerButton_Click(object sender, RoutedEventArgs e)
    {
        var _pickedFolder = await PickFolderAsync();
        if (_pickedFolder == null)
        {
            return;
        }

        _folder = _pickedFolder;
        _queryOptions = new QueryOptions
        {
            FolderDepth = FolderDepth.Deep,
            IndexerOption = IndexerOption.UseIndexerWhenAvailable,
        };

        _query = _folder.CreateFileQueryWithOptions(_queryOptions);

        _fileInformationFactory = new FileInformationFactory(_query, ThumbnailMode.SingleItem, 160,
            ThumbnailOptions.UseCurrentScale, delayLoad: false);

        var _vector = _fileInformationFactory.GetVirtualizedFilesVector();

        CollectionViewSource.Source = _vector;

        WorksCollectionViewSource.Source = Items;
    }

    private static async Task<StorageFolder> PickFolderAsync()
    {
        var folderPicker = new FolderPicker
        {
            SuggestedStartLocation = PickerLocationId.Desktop,
            ViewMode = PickerViewMode.Thumbnail
        };

        folderPicker.FileTypeFilter.Add("*");

        var _pickedFolder = await folderPicker.PickSingleFolderAsync();
        return _pickedFolder;
    }

}

编辑

问题已经缩小。这不是FileInformationFactory. ObservableCollection 有大量物品(在我的情况下约为 30k)也会出现问题,请参阅后面代码中的 ctor。在这个数字之下,所有项目都在网格内,而在这个数字之上,它们就离开了父容器。

4

1 回答 1

0

为了规避这个问题,ListView可以这样ClipVisual

 var visual = ElementCompositionPreview.GetElementVisual(listView);
            visual.Clip = Window.Current.Compositor.CreateInsetClip();

listView的名字在哪里ListView

学分转到 Github 上的 Ranjeshj https://github.com/microsoft/microsoft-ui-xaml/issues/1876

于 2020-01-24T09:25:30.153 回答