跳到主要内容
版本:0.10.x

Add Items to User Collection

Adding Albums to the Users Collection

Ok so now the user can find albums to purchase, it would be nice if the user could see which albums are in their collection. To do this we can add a similar UI to the MainWindow.

Modify the MainWindow.axaml so that it places the existing Button inside a panel. We can then add a TextBlock that we can show when the user has no music, to prompt them to buy some.

We can then use an ItemsControl instead of a ListBox as we did before. An ItemsControl is the exact same as a ListBox except it doesn't allow the user to select anything.

<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:Avalonia.MusicStore.ViewModels"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Avalonia.MusicStore.Views"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Avalonia.MusicStore.Views.MainWindow"
Icon="/Assets/avalonia-logo.ico"
Title="Avalonia.MusicStore"
TransparencyLevelHint="AcrylicBlur"
Background="Transparent"
ExtendClientAreaToDecorationsHint="True"
WindowStartupLocation="CenterScreen">

<Design.DataContext>
<vm:MainWindowViewModel />
</Design.DataContext>

<Panel>
<ExperimentalAcrylicBorder IsHitTestVisible="False">
<ExperimentalAcrylicBorder.Material>
<ExperimentalAcrylicMaterial
BackgroundSource="Digger"
TintColor="Black"
TintOpacity="1"
MaterialOpacity="0.65" />
</ExperimentalAcrylicBorder.Material>
</ExperimentalAcrylicBorder>

<Panel Margin="40">
<Button HorizontalAlignment="Right" VerticalAlignment="Top" Command="{Binding BuyMusicCommand}">
<PathIcon Data="{StaticResource store_microsoft_regular}" />
</Button>

<TextBlock IsVisible="{Binding CollectionEmpty}" Text="Its lonely in here. Purchase some music to get your collection started." HorizontalAlignment="Center" VerticalAlignment="Center" />

<ItemsControl Margin="0 40 0 0" Items="{Binding Albums}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>

<ItemsControl.ItemTemplate>
<DataTemplate>
<local:AlbumView Margin="0 0 20 20" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Panel>
</Panel>
</Window>

Just like in MusicStoreWindow.axaml we have to add xmlns:local="clr-namespace:Avalonia.MusicStore.Views" to the Window properties in order to use our custom control.

Now open MainWindowViewModel and add the following properties.

private bool _collectionEmpty;

public bool CollectionEmpty
{
get => _collectionEmpty;
set => this.RaiseAndSetIfChanged(ref _collectionEmpty, value);
}

public ObservableCollection<AlbumViewModel> Albums { get; } = new();

Notice again we use an ObservableCollection for the Albums property, and we add a simple CollectionEmpty property to tell us when the users music collection is empty.

In order to have the CollectionEmpty property updated we can add the following code to the constructor.

this.WhenAnyValue(x => x.Albums.Count)
.Subscribe(x => CollectionEmpty = x == 0);

Then in the constructor we can modify the BuyMusicCommand so that it adds the purchased Album to the list of Albums.

BuyMusicCommand = ReactiveCommand.CreateFromTask(async () =>
{
var store = new MusicStoreViewModel();

var result = await ShowDialog.Handle(store);

if (result != null)
{
Albums.Add(result);
}
});

Notice we check the result for null, this is because the user may have cancelled the dialog without selecting anything, in which case nothing should be added. If the dialog returns a result then we simply add it to the list of Albums.

Lets run the program and see if it works.

For the finishing touch we simply need to add persistence to the application.