【问题标题】:UWP change style of ListView DataTemplate in a MasterViewUWP 更改 MasterView 中 ListView DataTemplate 的样式
【发布时间】:2019-12-23 18:51:33
【问题描述】:

这是 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>

我正在尝试通过更改前景来突出显示正在播放音乐的 SongsListView 项目(它位于另一个列表视图中)。我在 ContainerContentChanging 中实现了它,但前景只会在重新加载页面后更改。我希望它实时更新。我该怎么做?

我注册了一个 MusicSwitching 事件,该事件会在当前播放的音乐发生变化时发生,这样我就可以将已播放项目的前景设置为黑色,将要播放的项目的前景设置为高亮颜色.

    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);
        });
    }

我可以先正确找到该项目,但容器为空。为什么?我认为是包含该项目的 DataTemplate。

【问题讨论】:

  • 你写的ArtistMasterDetailsView.ContainerFromItem方法不是很好,即使你拿到了,也只是外层materview的item的容器。所以最好的办法是使用 Binding。您可以将控件的 Foreground 绑定到 Music 类中的属性(例如 bool IsPlaying)。并在您的 MusicSwitching 方法中设置 current.IsPlaying false 和 next.IsPlaying true。
  • 绑定不会动态改变颜色。我需要重新加载页面以使其正常工作。 @Faywang-MSFT
  • 如果要接收绑定对象的属性变化通知,该属性所在的类需要继承自INotifyPropertyChanged,这样当你的属性值发生变化时,绑定到它的控件将收到更改通知。此外,您应该将模式更改为 OneWay。默认绑定模式是 OneTime,将绑定一次。如果您这样做,仍然可以'不改变,你能显示更多关于你的绑定的代码吗?
  • @Faywang-MSFT 你能检查一下这个link吗?我将 ObservableCollection 用于绑定集合,并将它们的所有模式设置为 OneWay。
  • @Faywang-MSFT 明确一点,我要更改的样式是SongsListView 的项目。其项目源在 ArtistsPage.xaml.cs 中定义,数据类型在 Models 文件夹中定义。

标签: c# xaml uwp master-detail listviewitem


【解决方案1】:

如果你想高亮SongsListView的一个项目,简单的方法是在Music类中设置一个属性(我看到你设置了一个IsPlaying方法,我把它改成一个属性)绑定到你想要的项目中的控件到hightlight.关于Binding,可以参考这个document

首先,您应该让 Music 类继承自 INotifyPropertyChanged 以监听属性更改通知。

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));
        }

然后,将该属性绑定到要突出显示的项目中的控件。

<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(); 
        }
    }

最后,当 MusicSwitching 被触发时,你可以重置 IsPlaying 属性,这样前景也会一起改变。

【讨论】:

  • 我没有将IsPlaying 设为属性,因为我将播放列表(音乐列表)保存到本地计算机。我在想这可能会浪费内存,因为我可以在运行时检查它。您认为这可能是个问题吗?
  • 没关系,不会有坏影响的。
  • 谢谢!我问了一个question,但没有得到好的答案。你能看一下吗?
猜你喜欢
  • 1970-01-01
  • 2016-11-25
  • 2019-04-13
  • 2021-12-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-24
  • 2023-03-30
  • 1970-01-01
相关资源
最近更新 更多