Search code examples
c#xamluwpwin-universal-app

UWP TabView OneWay x:Bind does not update


I have a TabView whose ItemTemplate is like this:

<controls:TabView.ItemTemplate>
    <DataTemplate x:DataType="data:Playlist">
        <local:HeaderedPlaylistControl
            IsPlaylist="True"
            Loaded="HeaderedPlaylistControl_Loaded"
            MusicCollection="{x:Bind Mode=OneWay}" />
    </DataTemplate>
</controls:TabView.ItemTemplate>

This is part of the HeaderedPlaylistControl:

<local:PlaylistControl
    AllowReorder="False"
    AlternatingRowColor="True"
    ItemsSource="{x:Bind MusicCollection.Songs, Mode=OneWay}">
    <local:PlaylistControl.Header>
        <controls:ScrollHeader Mode="Sticky">
            <UserControl>
                <Grid
                    x:Name="PlaylistInfoGrid"
                    Padding="10"
                    Background="{ThemeResource SystemColorHighlightColor}">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>
                    <Image
                        x:Name="PlaylistCover"
                        Grid.RowSpan="3"
                        Width="180"
                        Height="180"
                        Margin="20"
                        Source="Assets/monotone_bg_wide.png" />
                    <TextBlock
                        x:Name="PlaylistNameTextBlock"
                        Grid.Column="1"
                        Margin="0,5"
                        VerticalAlignment="Center"
                        FontSize="36"
                        Foreground="White"
                        Style="{StaticResource HeaderTextBlockStyle}"
                        Text="{x:Bind MusicCollection.Name, Mode=OneWay}" />
                    <TextBlock
                        x:Name="PlaylistInfoTextBlock"
                        Grid.Row="1"
                        Grid.Column="1"
                        Margin="0,5"
                        VerticalAlignment="Top"
                        Foreground="White"
                        Text="{x:Bind MusicCollection.Songs, Converter={StaticResource SongCountConverter}, Mode=OneWay}" />
                </Grid>
            </UserControl>
        </controls:ScrollHeader>
    </local:PlaylistControl.Header>
</local:PlaylistControl>

When I switch between tabs, the HeaderedPlaylistControl doesn't update it's content. Why is that?

Is it because of the MusicCollection property (it is of type Playlist) doesn't notify the binding when switching tabs? If so, where should I put the notification? The definition of Playlist is here.

HeaderedPlaylistControl is here:


Solution

  • Yes, as you suspected, the problem is that the MusicCollection property is an ordinary property which does not notify about changes. To make your code work, you need to make the MusicCollection property a dependency property (see docs). This is a kind of properties which are best for data-bound properties of visual controls and have many additional features as well.

    public static readonly DependencyProperty MusicCollectionProperty =
        DependencyProperty.Register(
            nameof(MusicCollection), typeof(Playlist),
            typeof(HeaderedPlaylistControl), null
        );
    
    public Playlist MusicCollection
    {
        get { return (bool)GetValue(MusicCollectionProperty); }
        set { SetValue(MusicCollectionProperty, value); }
    }