1

This is the structure of the XAML:

    <controls:MasterDetailsView
        ItemsSource="{x:Bind Artists}">
        <controls:MasterDetailsView.MasterHeader>
            // Some Code
        </controls:MasterDetailsView.MasterHeader>
        <controls:MasterDetailsView.ItemTemplate>
            // Some Code
        </controls:MasterDetailsView.ItemTemplate>
        <controls:MasterDetailsView.DetailsTemplate>
            <DataTemplate x:DataType="data:ArtistView">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="*" />
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>
                    <RelativePanel HorizontalAlignment="Stretch">
                        // Some Code
                    </RelativePanel>
                    <ListView
                        x:Name="AlbumsListView"
                        Grid.Row="1"
                        HorizontalAlignment="Stretch"
                        ItemsSource="{x:Bind Albums}"
                        SelectionMode="None">
                        <ListView.ItemTemplate>
                            <DataTemplate x:DataType="data:AlbumView">
                                <Grid Margin="10,0,0,30">
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="Auto" />
                                        <RowDefinition Height="*" />
                                    </Grid.RowDefinitions>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="*" />
                                    </Grid.ColumnDefinitions>
                                    <RelativePanel>
                                        // Some Code
                                    </RelativePanel>
                                    <ListView
                                        x:Name="SongsListView"
                                        Grid.Row="1"
                                        HorizontalAlignment="Stretch"
                                        ContainerContentChanging="SongsListView_ContainerContentChanging"
                                        IsItemClickEnabled="True"
                                        ItemClick="SongsListView_ItemClick"
                                        ItemsSource="{x:Bind Songs}"
                                        SelectionMode="Single">
                                        <ListView.ItemTemplate>
                                            <DataTemplate x:DataType="local:Music">
                                                // Some Code
                                            </DataTemplate>
                                        </ListView.ItemTemplate>
                                    </ListView>
                                </Grid>
                            </DataTemplate>
                        </ListView.ItemTemplate>
                    </ListView>
                </Grid>
            </DataTemplate>
        </controls:MasterDetailsView.DetailsTemplate>
    </controls:MasterDetailsView>

I am trying to highlight an item of SongsListView (it's inside another listview) whose music is playing by changing the foreground. I implemented it in the ContainerContentChanging but the foreground will only be changed after reload the page. I want it to be updated in real time. How can I do that?

I registered a MusicSwitching event which will take place when the current playing music is changed, so that I can set the foreground of the item that has been played to black, and the foreground of the item to be played to a highlight color.

    public async void MusicSwitching(Music current, Music next)
    {
        await Dispatcher.RunAsync(CoreDispatcherPriority.High, () =>
        {
            var item = ArtistMasterDetailsView.Items.First((a) => (a as ArtistView).Name == next.Artist);
            var container = ArtistMasterDetailsView.ContainerFromItem(item);
        });
    }

I can first find the item correctly, but the container is null. Why? I thought it is the DataTemplate that contains the item.

  • The method **ArtistMasterDetailsView.ContainerFromItem** you wrote is not very good, even if you get it, it is just the container of the item from outer materview.So the best way is use **Binding**.You can bind the Foreground of controls to a property(e.g. bool IsPlaying) in Music class.And in your MusicSwitching method to set the current.IsPlaying false and next.IsPlaying true. – Faywang - MSFT Aug 19 '19 at 09:14
  • Binding doesn't change color on the fly. I need to reload the page to make it work. @Faywang-MSFT –  Aug 19 '19 at 12:51
  • If you want to receive property change notifications from the bound object, the class in which this property is located needs to inherit from **INotifyPropertyChanged**, so that when your property value changes, the control bound to it will be notified with the change.In addition,you should change the Mode to the **OneWay**.The default binding mode is OneTime which will bind once.If you do the same, still can't change, can you show more code about your binding? – Faywang - MSFT Aug 20 '19 at 06:45
  • @Faywang-MSFT Could you please check this [link](https://github.com/SeakyLuo/SMPlayer/blob/master/SMPlayer/ArtistsPage.xaml)? I used ObservableCollection for the bound collections and have set all their modes to OneWay. –  Aug 22 '19 at 00:07
  • @Faywang-MSFT Just to be clear, the style I want to change is `SongsListView`'s item. Its item source is defined in the **ArtistsPage.xaml.cs** and the datatype is defined in the **Models** folder. –  Aug 22 '19 at 00:15

1 Answers1

0

If you want to highlight an item of SongsListView,the simple way is to set a property(I saw you have set a IsPlaying method,I changed it to a property) in Music class to bind to the control in item you want to hightlight.About Binding,you can refer to this document.

First, you should let the Music class inherits from INotifyPropertyChanged to listen property change notifications.

public class Music : IComparable<Music>, INotifyPropertyChanged
    {
        ......
        public event PropertyChangedEventHandler PropertyChanged = delegate { };
        public bool IsPlaying {

            set { 
                IsMusicPlaying = value;
                OnPropertyChanged();
            }
            get {
                return IsMusicPlaying;
            }
        }

        public void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            // Raise the PropertyChanged event, passing the name of the property whose value has changed.
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

Then,bind the property to the control in item you want to highlight.

<Page.Resources>
        <local:ColorConvert x:Name="MyConvert"></local:ColorConvert>
</Page.Resources>
<FontIcon
         x:Name="PlayingIcon"
         Margin="0,0,16,0"
         FontFamily="Segoe MDL2 Assets"
         Foreground="{StaticResource SystemColorHighlightColor}"
         Glyph="&#xE767;"
         RelativePanel.AlignLeftWithPanel="True"
         Visibility="{Binding Name, Converter={StaticResource MusicVisibilityConverter}}" />
<TextBlock
         x:Name="MusicNameTextBlcok"
         Grid.Column="1"
         Width="720"
         Text="{x:Bind Name}" 
         Foreground="{x:Bind IsPlaying,Converter={StaticResource MyConvert},Mode=OneWay}"/>

.cs

public class ColorConvert : IValueConverter
    {
        // this does not include sublevel menus right now
        public object Convert(object value, Type targetType, object parameter, string language)
        {
            if (value.ToString() == "False")
            {
                return Helper.BlackBrush;
            }
            else
            {
                return Helper.GetHighlightBrush();
            }

        }

        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            throw new NotImplementedException(); 
        }
    }

Finally,when the MusicSwitching is triggered,you can reset IsPlaying property.In this case,the foreground will also change together.

Faywang - MSFT
  • 5,798
  • 1
  • 5
  • 8
  • I didn't make `IsPlaying` a property because I saved the playlist (a list of music) to my local computer. I was thinking that this might be a waste of memory since I can check it at run time. Do you think this might be an issue? –  Aug 22 '19 at 12:18
  • It's okay, it's not going to make a bad impact. – Faywang - MSFT Aug 23 '19 at 05:42
  • Thank you! I have asked a [question](https://stackoverflow.com/questions/57478990/uwp-visualstatemanager-pointerover-does-not-work) that has not received a good answer. Could you please take a look at that? –  Aug 24 '19 at 01:19