UWP change style of ListView DataTemplate in a MasterView

别等时光非礼了梦想. 提交于 2019-12-11 06:26:22

问题


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.


回答1:


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.



来源:https://stackoverflow.com/questions/57541703/uwp-change-style-of-listview-datatemplate-in-a-masterview

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!