Search code examples
xamldata-bindinguwpasync-awaitpivot

How to use xaml pivot with async methods


I'm using pivot control to list the content of a collection of videos that are obtained from an async method.

I have 2 pivot item, one for favorite, that will have elements that the user will have selected in the other pivot which list all videos.

Right now, I have a working xaml file. The file looks like this

        <Grid.RowDefinitions>
            <RowDefinition Height = "auto"/>
            <RowDefinition Height = "*"/>
        </Grid.RowDefinitions>
        <TextBlock Text="Video" FontSize="30" Margin="10,0,0,0"/>
        <Pivot Grid.Row = "1">

            <PivotItem Header="Favorite Videos">
                <ItemsControl ItemsSource="{x:Bind ViewModel.FavoriteVideos, Mode=OneWay}">
                    <ItemsControl.ItemTemplate>
                        <DataTemplate x:DataType="models:VideoModel">
                            <Grid Height="40">
                                <TextBlock VerticalAlignment="Center" Text="{x:Bind  Title}"/>
                            </Grid>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </PivotItem>

            <PivotItem Header="All Videos" >
                <ItemsControl ItemsSource="{x:Bind ViewModel.AllVideos, Mode=OneWay}" >
                    <ItemsControl.ItemTemplate>
                        <DataTemplate x:DataType="models:VideoModel">
                            <StackPanel Orientation="Horizontal">
                                <Image Source="{x:Bind Cover}" HorizontalAlignment="Left" Width="100"/>
                                <TextBlock VerticalAlignment="Center" Text="{x:Bind Title}"/>
                                <ToggleSwitch Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Center" IsOn="{x:Bind IsFavorite, Mode=TwoWay}"/>
                            </StackPanel>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </PivotItem>


        </Pivot>
    </Grid>

The code behind the ViewModel.AllVideos is this :

namespace VideoManager.ViewModels
{
    public class VideoViewModel
    {
        public List<VideoModel> AllVideos = new List<VideoModel>();
        public ObservableCollection<VideoModel> FavoriteVideos = new ObservableCollection<VideoModel>();

        public VideoViewModel()
        {
            InitVideos();

        }

        private async void InitVideos()
        {
            var files = await KnownFolders.VideosLibrary.GetFilesAsync();
            foreach (var file in files)
            {
                if (file != null)
                {
                    var thumbnail = await file.GetThumbnailAsync(ThumbnailMode.VideosView, 50, ThumbnailOptions.ReturnOnlyIfCached);
                    VideoModel video = new VideoModel();
                    video.PropertyChanged += IsFavoritePropertyChanged;
                    video.Title = file.Name;
                    if (thumbnail != null)
                    {
                        BitmapImage bitmapImage = new BitmapImage();
                        InMemoryRandomAccessStream randomAccessStream = new InMemoryRandomAccessStream();
                        await RandomAccessStream.CopyAsync(thumbnail, randomAccessStream);
                        randomAccessStream.Seek(0);
                        await bitmapImage.SetSourceAsync(randomAccessStream);
                        video.Cover = bitmapImage;
                    }

                    AllVideos.Add(video);
                    if (video.IsFavorite)
                    {
                        FavoriteVideos.Add(video);
                    }
                }

            }
        }

        public void IsFavoritePropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            VideoModel toggledVideo = sender as VideoModel;
            if (toggledVideo.IsFavorite)
            {
                FavoriteVideos.Add(toggledVideo);
            }
            else
            {
                FavoriteVideos.Remove(toggledVideo);
            }
        }
    }

}

It works fine but if I change the order of the PivotItem and I put the PivotItem All videos before the PivotItem FavoriteVideos then nothing will appear on the screen. I guess it has something to with the async method.

So my question is how to make this work whatever the order of PivotItem are ?

Thank you


Solution

  • Using ObservableCollection will resolve this issue. The List Class has not implemented the INotifyPropertyChanged Interface , it will not notify the UI when it's been updated.

    public ObservableCollection<VideoModel> AllVideos = new ObservableCollection<VideoModel>();