Обновление информации Хорошо, мои извинения Мне пришлось пересмотреть мой вопрос и название. Но сузить проблему было нелегко, несмотря на несколько проведенных нами испытаний. Ниже вы найдете новый код, приводящий к необъяснимой ошибке, и более старую версию вопроса, оставленную здесь по старым причинам. Воспроизвести проблему несложно.
Обновленный код Возьмите 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()
.
Вопрос
Как решить эту проблему без потери виртуализации?
Спасибо
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 в коде позади. Ниже этого числа все элементы находятся в сетке, а выше они выходят из родительского контейнера.