Search code examples
uwpcollectionviewsource

How to get an update on CollectionViewSource.View.Count in UWP


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!


Solution

  • 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
            }
        }