Highlight active playlist. Various optimizations and fixes.

This commit is contained in:
2026-08-05 00:50:56 -04:00
parent 3c3cf37cd5
commit 1d45826c38
14 changed files with 327 additions and 55 deletions

View File

@@ -12,8 +12,34 @@
d:DataContext="{d:DesignInstance Type=vm:PlaylistsViewModel, IsDesignTimeCreatable=True}"
mc:Ignorable="d">
<UserControl.Resources>
<SolidColorBrush x:Key="PlaylistItemIconBrush" Color="#dddddd"/>
<SolidColorBrush x:Key="PlaylistItemTitleBrush" Color="#dddddd"/>
<SolidColorBrush x:Key="PlaylistItemSubtitleBrush" Color="#aaaaaa"/>
<!-- Playlist Icon Path -->
<Style x:Key="PlaylistIconPath" TargetType="PathIcon">
<Setter Property="Foreground" Value="{StaticResource PlaylistItemIconBrush}"/>
</Style>
<Style x:Key="SelectedPlaylistIconPath" TargetType="PathIcon" BasedOn="{StaticResource PlaylistIconPath}">
<Setter Property="Foreground" Value="{StaticResource AccentTextFillColorPrimaryBrush}"/>
</Style>
<!-- Playlist Title Text Block -->
<Style x:Key="PlaylistTitleTextBlock" TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource PlaylistItemTitleBrush}"/>
<Setter Property="FontSize" Value="15"/>
<Setter Property="FontWeight" Value="Medium"/>
<Setter Property="LineStackingStrategy" Value="BlockLineHeight"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="TextTrimming" Value="CharacterEllipsis"/>
<Setter Property="LineHeight" Value="0"/>
</Style>
<Style x:Key="SelectedPlaylistTitleTextBlock" TargetType="TextBlock" BasedOn="{StaticResource PlaylistTitleTextBlock}">
<Setter Property="Foreground" Value="{StaticResource AccentTextFillColorPrimaryBrush}"/>
</Style>
<!-- Playlist Item Subtitle Text Block -->
<Style x:Key="PlaylistSubtitleTextBlock" TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource PlaylistItemSubtitleBrush}"/>
@@ -23,26 +49,31 @@
<Setter Property="LineHeight" Value="0"/>
</Style>
<Style x:Key="SelectedPlaylistSubtitleTextBlock" TargetType="TextBlock" BasedOn="{StaticResource PlaylistSubtitleTextBlock}">
<Setter Property="Foreground" Value="{StaticResource AccentTextFillColorSecondaryBrush}"/>
</Style>
<DataTemplate x:Key="PlaylistTemplate" x:DataType="vm:PlaylistItemViewModel">
<Grid>
<Grid x:Name="PlaylistListViewItem">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="200" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Orientation="Horizontal" Spacing="8" VerticalAlignment="Center">
<Viewbox Height="24" Width="24">
<PathIcon Data="{StaticResource MusicNoteList}" />
<PathIcon x:Name="MusicNoteListPathIcon" Data="{StaticResource MusicNoteList}" />
</Viewbox>
<TextBlock Text="{x:Bind Name, Mode=OneWay}" FontSize="16" VerticalAlignment="Center" />
<TextBlock x:Name="PlaylistTitleTextBlock" Text="{x:Bind Name, Mode=OneWay}" Style="{StaticResource PlaylistTitleTextBlock}" />
</StackPanel>
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Center" Spacing="8">
<TextBlock Text="{x:Bind Summary, Mode=OneWay}" Style="{StaticResource PlaylistSubtitleTextBlock}" />
<TextBlock x:Name="PlaylistSubtitleTextBlock" Text="{x:Bind Summary, Mode=OneWay}" Style="{StaticResource PlaylistSubtitleTextBlock}" />
</StackPanel>
</Grid>
</DataTemplate>
</UserControl.Resources>
<Grid Margin="10">
<ListView
Name="PlaylistsListView"
ItemsSource="{Binding Playlists, Mode=OneWay}"
SelectedItem="{Binding SelectedPlaylist, Mode=TwoWay}"
ItemTemplate="{StaticResource PlaylistTemplate}">

View File

@@ -1,12 +1,99 @@
using CommunityToolkit.WinUI;
using Harmonia.WinUI.ViewModels;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using System.ComponentModel;
namespace Harmonia.WinUI.Views;
public sealed partial class PlaylistsView : UserControl
{
private readonly PlaylistsViewModel _viewModel;
public PlaylistsView()
{
InitializeComponent();
_viewModel = (PlaylistsViewModel)DataContext;
_viewModel.PropertyChanging += OnViewModelPropertyChanging;
_viewModel.PropertyChanged += OnViewModelPropertyChanged;
}
private void OnViewModelPropertyChanging(object? sender, PropertyChangingEventArgs e)
{
switch (e.PropertyName)
{
case nameof(_viewModel.ActivePlaylist):
UpdateListViewItemStyle(PlaylistItemStyle.Normal);
break;
}
}
private void OnViewModelPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case nameof(_viewModel.ActivePlaylist):
UpdateListViewItemStyle(PlaylistItemStyle.Selected);
break;
}
}
private void UpdateListViewItemStyle(PlaylistItemStyle style)
{
ListViewItem listViewItem = (ListViewItem)PlaylistsListView.ContainerFromItem(_viewModel.ActivePlaylist);
if (listViewItem is null)
return;
FrameworkElement? frameworkElement = TryGetFrameworkElement(listViewItem, "PlaylistListViewItem");
if (frameworkElement == null)
return;
string playlistItemIconBrushName = style == PlaylistItemStyle.Selected ? "SelectedPlaylistIconPath" : "PlaylistIconPath";
string playlistItemTitleBrushName = style == PlaylistItemStyle.Selected ? "SelectedPlaylistTitleTextBlock" : "PlaylistTitleTextBlock";
string playlistItemSubtitleBrushName = style == PlaylistItemStyle.Selected ? "SelectedPlaylistSubtitleTextBlock" : "PlaylistSubtitleTextBlock";
UpdateElementStyle(frameworkElement, "MusicNoteListPathIcon", playlistItemIconBrushName);
UpdateElementStyle(frameworkElement, "PlaylistTitleTextBlock", playlistItemTitleBrushName);
UpdateElementStyle(frameworkElement, "PlaylistSubtitleTextBlock", playlistItemSubtitleBrushName);
}
private static FrameworkElement? TryGetFrameworkElement(ListViewItem listViewItem, string elementName)
{
if (listViewItem.Name == elementName)
{
return listViewItem;
}
else
{
if (listViewItem.FindDescendant(elementName) is not FrameworkElement frameworkElement)
return null;
return frameworkElement;
}
}
private void UpdateElementStyle(FrameworkElement dependencyObject, string elementName, string resourceName)
{
if (dependencyObject.FindDescendant(elementName) is not FrameworkElement frameworkElement)
return;
Resources.TryGetValue(resourceName, out object? resource);
if (resource == null)
Application.Current.Resources.TryGetValue(resourceName, out resource);
if (resource is not Style style)
return;
frameworkElement.Style = style;
}
}
public enum PlaylistItemStyle
{
Normal,
Selected
}