I am retrieving the FileInformation.DisplayName
property of circa 5k files in a folder using FileInformationFactory.GetVirtualizedFilesVector()
to display them in a GridView in UWP via a CollectionViewSource
. While the display works, I fail to obtain the proper count of the items that have been retrieved.
I am aware that I can do this by awaiting GetFilesAsync
and count but this kills the speed purpose of using the virtualized vector, and hence I would like to avoid it.
Here is the XAML
xmlns:ba="using:Windows.Storage.BulkAccess"
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Margin="16">
<StackPanel Orientation="Horizontal">
<AppBarButton Icon="Folder" Click="AppBarButton_Click" LabelPosition="Collapsed"/>
<AppBarButton Icon="Refresh" Click="RefreshAppBarButton_Click" LabelPosition="Collapsed"/>
</StackPanel>
<TextBlock x:Name="infoTextBlock" FontWeight="Medium"/>
</StackPanel>
<GridView Grid.Row="1" Grid.Column="1"
ItemsSource="{x:Bind FileCollectionViewSource.View, Mode=OneWay}">
<GridView.ItemTemplate>
<DataTemplate x:DataType="ba:FileInformation">
<TextBlock Text="{x:Bind DisplayName}"/>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</Grid>
And the code behind
private StorageFolder _folder;
public CollectionViewSource FileCollectionViewSource { get; set; } = new CollectionViewSource();
private async void AppBarButton_Click(object sender, RoutedEventArgs e)
{
var folderPicker = new FolderPicker
{
SuggestedStartLocation = PickerLocationId.PicturesLibrary,
ViewMode = PickerViewMode.Thumbnail
};
folderPicker.FileTypeFilter.Add("*");
_folder = await folderPicker.PickSingleFolderAsync();
if (_folder != null)
{
GetFileVectors();
}
else
{
infoTextBlock.Text = "Pick folder";
}
}
private void GetFileVectors()
{
var queryOptions = new QueryOptions
{
FolderDepth = FolderDepth.Deep,
IndexerOption = IndexerOption.UseIndexerWhenAvailable
};
var fileQuery = _folder.CreateFileQueryWithOptions(queryOptions);
var fileInformationFactory = new FileInformationFactory(fileQuery, ThumbnailMode.SingleItem, Constants.Thumbnail_Size,
ThumbnailOptions.UseCurrentScale, false);
var filesVector = fileInformationFactory.GetVirtualizedFilesVector();
FileCollectionViewSource.Source = filesVector;
var count = FileCollectionViewSource.View.Count;
infoTextBlock.Text = $"View count {count}";//Returns 0
}
private void RefreshAppBarButton_Click(object sender, RoutedEventArgs e)
{
infoTextBlock.Text = $"View count {FileCollectionViewSource.View.Count}";//returns the correct count
}
Results:
When I choose a folder, the method GetFileVectors() is invoked, it performs the bulk search and sets FileCollectionViewSource.Source = filesVector;
, and FileCollectionViewSource.View
is OneWay
bound to the GridView
. However, FileCollectionViewSource.View.Count
returns 0 at this stage.
If now I click on the refresh button RefreshAppBarButton_Click
then the exact count is returned.
I can imagine that FileCollectionViewSource.View
needs some time to settle, and indeed setting an await Task.Delay(1000)
before printing out FileCollectionViewSource.View.Count
works, but I am looking at a way to update the TextBlock
when FileCollectionViewSource.View
is done.
Is there a way to do that automatically by some event or other? Thanks!
Following Nico Zhu - MSFT, fire an event after the source has been setFileCollectionViewSource.View.VectorChanged += View_VectorChanged;
then
private void View_VectorChanged(IObservableVector<object> sender, IVectorChangedEventArgs @event)
{
if (@event.CollectionChange == CollectionChange.Reset)
{
infoTextBlock.Text = $"{FileCollectionViewSource.View.Count} ";//returns the correct count
}
}