ItemsStackPanel выходит за пределы контейнера Grid для большого источника - PullRequest
0 голосов
/ 22 января 2020

Обновление информации Хорошо, мои извинения Мне пришлось пересмотреть мой вопрос и название. Но сузить проблему было нелегко, несмотря на несколько проведенных нами испытаний. Ниже вы найдете новый код, приводящий к необъяснимой ошибке, и более старую версию вопроса, оставленную здесь по старым причинам. Воспроизвести проблему несложно.

Обновленный код Возьмите Listview, привязанный к ObservableCollection, и заполните его большим количеством элементов, в нашем случае более 30 тыс. Конечный результат заключается в том, что по мере увеличения количества элементов 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 связывает ItemsSource с CollectionViewSource.View, для которого для источника установлено значение FileInformationFactory. В приведенном ниже пользовательском интерфейсе представлена ​​кнопка для выбора более 100 изображений для заполнения ListView (см. Раздел «Редактирование»).

Второй ListView связывает ItemsSource с другим CollectionViewSource.View, для которого установлен источник тривиальный ObservableCollection.

Результат

Первый ListView выходит за пределы контейнера сетки всякий раз, когда ориентация ItemsStackPanel установлена ​​на Horizontal. Переключение ItemsSource не решает эту проблему, следовательно, указывает, что эта проблема задается c для метода FileInformationFactory.GetVirtualizedFilesVector().

enter image description here

Вопрос

Как решить эту проблему без потери виртуализации?

Спасибо

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 в коде позади. Ниже этого числа все элементы находятся в сетке, а выше они выходят из родительского контейнера.

1 Ответ

0 голосов
/ 24 января 2020

Чтобы обойти эту проблему с помощью ListView, можно Clip Visual как таковое

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

, где listView - это имя ListView.

Кредиты go Ранжеш на Github https://github.com/microsoft/microsoft-ui-xaml/issues/1876

...