fixed up media controller

This commit is contained in:
TheXamlGuy
2024-02-03 19:58:54 +00:00
parent 221c46218f
commit 23c398ea43
35 changed files with 217 additions and 195 deletions
@@ -17,7 +17,7 @@
<None Remove="bin/Debug/net8.0-windows10.0.19041.0/Hyperbar.Windows.Controls.pri" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.5.231202003-experimental1" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.5.240124002-experimental2" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26031-preview" />
</ItemGroup>
<ItemGroup>
@@ -9,7 +9,7 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.5.231202003-experimental1" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.5.240124002-experimental2" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26031-preview" />
</ItemGroup>
<ItemGroup>
@@ -5,9 +5,9 @@ using Windows.Storage.Streams;
namespace Hyperbar.UI.Windows;
public class StreamToImageSourceConverter :
ValueConverter<Stream, ImageSource>
ValueConverter<byte[], ImageSource>
{
protected override ImageSource? ConvertTo(Stream value,
protected override ImageSource? ConvertTo(byte[] value,
Type? targetType,
object? parameter,
string? language)
@@ -17,8 +17,8 @@ public class StreamToImageSourceConverter :
return default;
}
IRandomAccessStream randomAccessStream =
WindowsRuntimeStreamExtensions.AsRandomAccessStream(value);
MemoryStream memoryStream = new(value);
IRandomAccessStream randomAccessStream = memoryStream.AsRandomAccessStream();
BitmapImage bitmapImage = new();
bitmapImage.SetSource(randomAccessStream);
@@ -12,7 +12,7 @@
<PackageReference Include="CommunityToolkit.WinUI" Version="7.1.2" />
<PackageReference Include="CommunityToolkit.WinUI.UI.Controls" Version="7.1.2" />
<PackageReference Include="CommunityToolkit.WinUI.UI.Controls.Primitives" Version="7.1.2" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.5.231202003-experimental1" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.5.240124002-experimental2" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26031-preview" />
<PackageReference Include="Microsoft.Xaml.Behaviors.WinUI.Managed" Version="2.0.9" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
@@ -0,0 +1,13 @@
using CommunityToolkit.Mvvm.Input;
namespace Hyperbar.Widget.MediaController.Windows;
public interface IMediaButtonViewModel :
IObservableViewModel
{
IRelayCommand? InvokeCommand { get; set; }
bool IsEnabled { get; set; }
string? State { get; set; }
}
@@ -1,3 +1,3 @@
namespace Hyperbar.Widget.MediaController.Windows;
public record Previous : INotification;
public record MediaButton(bool IsEnabled);
@@ -4,7 +4,8 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:interactions="using:Microsoft.Xaml.Interactions.Core"
xmlns:interactivity="using:Microsoft.Xaml.Interactivity">
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:triggers="using:CommunityToolkit.WinUI.UI.Triggers">
<UserControl.Resources>
<SolidColorBrush x:Key="ButtonBackground" Color="Transparent" />
<SolidColorBrush x:Key="ButtonBorderBrush" Color="Transparent" />
@@ -16,18 +17,49 @@
<x:Double x:Key="ButtonHeight">40</x:Double>
</UserControl.Resources>
<Button
x:Name="Button"
Width="{StaticResource ButtonWidth}"
Height="{StaticResource ButtonHeight}"
Padding="{StaticResource ButtonPadding}"
Command="{Binding Click}"
Content="{Binding Icon}"
Command="{x:Bind ViewModel.InvokeCommand}"
Content="{x:Bind ViewModel.State}"
FontFamily="{StaticResource SymbolThemeFontFamily}"
FontSize="16"
ToolTipService.ToolTip="{Binding Text}">
IsEnabled="False">
<interactivity:Interaction.Behaviors>
<interactions:EventTriggerBehavior EventName="Loaded">
<interactions:InvokeCommandAction Command="{Binding Initialize}" />
<interactions:InvokeCommandAction Command="{x:Bind ViewModel.InitializeCommand}" />
</interactions:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="MediaPreviousButtonState">
<VisualState.StateTriggers>
<triggers:IsEqualStateTrigger Value="{Binding State}" To="MediaPreviousButton" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="Button.Content" Value="&#xE892;" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="MediaNextButtonState">
<VisualState.StateTriggers>
<triggers:IsEqualStateTrigger Value="{Binding State}" To="MediaNextButton" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="Button.Content" Value="&#xE893;" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
<VisualStateGroup>
<VisualState x:Name="IsEnabledState">
<VisualState.StateTriggers>
<triggers:IsEqualStateTrigger Value="{Binding IsEnabled}" To="True" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="Button.IsEnabled" Value="True" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Button>
</UserControl>
@@ -9,5 +9,5 @@ public sealed partial class MediaButtonView :
public MediaButtonView() =>
this.InitializeComponent(ref _contentLoaded);
private MediaButtonViewModel ViewModel => (MediaButtonViewModel)DataContext;
private IMediaButtonViewModel ViewModel => (IMediaButtonViewModel)DataContext;
}
@@ -3,42 +3,33 @@ using CommunityToolkit.Mvvm.Input;
namespace Hyperbar.Widget.MediaController.Windows;
[NotificationHandler(nameof(PlaybackButtonType))]
public partial class MediaButtonViewModel(IServiceFactory serviceFactory,
public partial class MediaButtonViewModel<TMediaButton>(IServiceFactory serviceFactory,
IMediator mediator,
IDisposer disposer,
ITemplateFactory templateFactory,
PlaybackButtonType playbackButtonType,
Guid guid = default,
string? text = null,
string? icon = null,
RelayCommand? command = null) :
WidgetButtonViewModel(serviceFactory, mediator, disposer, templateFactory, guid, text, icon, command)
IRelayCommand invokeCommand) :
WidgetComponentViewModel(serviceFactory, mediator, disposer, templateFactory),
INotificationHandler<Changed<TMediaButton>>,
IMediaButtonViewModel
where TMediaButton :
MediaButton
{
[ObservableProperty]
private PlaybackButtonType playbackButtonType = playbackButtonType;
private IRelayCommand? invokeCommand = invokeCommand;
public Task Handle(Changed<MediaControllerPlaybackStatus> notification,
[ObservableProperty]
private bool isEnabled;
[ObservableProperty]
private string? state = $"{typeof(TMediaButton).Name}";
public Task Handle(Changed<TMediaButton> args,
CancellationToken cancellationToken)
{
if (notification.Value is MediaControllerPlaybackStatus information)
{
//switch (buttonType)
//{
// case PlaybackButtonType.Play:
// Visible = information.Status is PlaybackStatus.Paused;
// break;
// case PlaybackButtonType.Pause:
// Visible = information.Status is PlaybackStatus.Playing;
// break;
//}
}
IsEnabled = args.Value is not null && args.Value.IsEnabled;
return Task.CompletedTask;
}
//public override Task OnInitializeAsync()
//{
// await Mediator.PublishAsync<Request<PlaybackInformation>>();
//}
public override async Task InitializeAsync() =>
await Mediator.PublishAsync<Request<TMediaButton>>();
}
@@ -1,13 +1,16 @@
using Windows.Media.Control;
using System.Collections.Concurrent;
using System.Diagnostics;
using Windows.Media.Control;
using Windows.Storage.Streams;
namespace Hyperbar.Widget.MediaController.Windows;
public class MediaController :
INotificationHandler<Play>,
INotificationHandler<Pause>,
INotificationHandler<Request<MediaControllerPlaybackStatus>>,
INotificationHandler<Request<MediaPrevious>>,
INotificationHandler<Request<MediaNext>>,
INotificationHandler<Request<MediaInformation>>,
INotificationHandler<Request<MediaPreviousButton>>,
INotificationHandler<Request<MediaNextButton>>,
IDisposable
{
private readonly AsyncLock asyncLock = new();
@@ -38,74 +41,96 @@ public class MediaController :
disposer.Dispose(this);
}
public async Task Handle(Play notification,
CancellationToken cancellationToken)
{
await session.TryPlayAsync();
await UpdateMediaPlaybackPropertiesAsync();
}
public async Task Handle(Pause notification,
CancellationToken cancellationToken)
{
await session.TryPauseAsync();
await UpdateMediaPlaybackPropertiesAsync();
}
public async Task Handle(Request<MediaControllerPlaybackStatus> args,
CancellationToken cancellationToken) => await UpdateMediaPlaybackPropertiesAsync();
public async Task Handle(Request<MediaInformation> args,
CancellationToken cancellationToken) => await UpdateMediaPropertiesAsync();
CancellationToken cancellationToken) => await UpdateMediaInformationAsync();
public async Task Handle(Request<MediaNext> args,
CancellationToken cancellationToken)
{
await session.TrySkipNextAsync();
await UpdateMediaStateAsync();
}
public async Task Handle(Request<MediaPrevious> args, CancellationToken cancellationToken)
{
await session.TrySkipPreviousAsync();
await UpdateMediaStateAsync();
}
public async Task Handle(Request<MediaPreviousButton> args,
CancellationToken cancellationToken) => await UpdateMediaStateAsync();
public async Task Handle(Request<MediaNextButton> args,
CancellationToken cancellationToken) => await UpdateMediaStateAsync();
private async void OnMediaPropertiesChanged(GlobalSystemMediaTransportControlsSession sender,
MediaPropertiesChangedEventArgs args) => await UpdateMediaPropertiesAsync();
MediaPropertiesChangedEventArgs args)
{
await UpdateMediaInformationAsync();
await UpdateMediaStateAsync();
}
private async void OnPlaybackInfoChanged(GlobalSystemMediaTransportControlsSession sender,
PlaybackInfoChangedEventArgs args) => await UpdateMediaPlaybackPropertiesAsync();
PlaybackInfoChangedEventArgs args) => await UpdateMediaStateAsync();
private async Task UpdateMediaPlaybackPropertiesAsync()
{
using (await asyncLock)
private async Task UpdateMediaInformationAsync()
{
try
{
GlobalSystemMediaTransportControlsSessionPlaybackInfo playbackInfo = session.GetPlaybackInfo();
if (playbackInfo.PlaybackStatus != playbackStatus)
{
playbackStatus = playbackInfo.PlaybackStatus;
await mediator.PublishAsync(new Changed<MediaControllerPlaybackStatus>(
new MediaControllerPlaybackStatus((PlaybackStatus)playbackStatus)));
}
}
catch
{
}
}
}
private async Task UpdateMediaPropertiesAsync()
{
using (await asyncLock)
{
try
{
GlobalSystemMediaTransportControlsSessionMediaProperties mediaProperties =
await session.TryGetMediaPropertiesAsync();
IRandomAccessStreamWithContentType? randomAccessStream = null;
byte[]? buffer = null;
if (mediaProperties.Thumbnail is not null)
{
randomAccessStream =
IRandomAccessStreamWithContentType randomAccessStream =
await mediaProperties.Thumbnail.OpenReadAsync();
var stream = randomAccessStream.AsStream();
using MemoryStream memoryStream = new();
await stream.CopyToAsync(memoryStream);
buffer = memoryStream.ToArray();
}
await mediator.PublishAsync(new Changed<MediaInformation>(new MediaInformation(mediaProperties.Title,
mediaProperties.Artist, randomAccessStream is not null ? randomAccessStream.AsStream() : default)));
mediaProperties.Artist, buffer)));
}
catch
{
}
}
private bool isPreviousEnabled;
private bool isNextEnabled;
private async Task UpdateMediaStateAsync()
{
try
{
GlobalSystemMediaTransportControlsSessionPlaybackInfo playbackInfo =
session.GetPlaybackInfo();
bool isPreviousEnabled = playbackInfo.Controls.IsPreviousEnabled;
if (this.isPreviousEnabled != isPreviousEnabled)
{
await mediator.PublishAsync(new Changed<MediaPreviousButton>(new
MediaPreviousButton(isPreviousEnabled)));
this.isPreviousEnabled = isPreviousEnabled;
}
bool isNextEnabled = playbackInfo.Controls.IsNextEnabled;
if (this.isNextEnabled != isNextEnabled)
{
await mediator.PublishAsync(new Changed<MediaNextButton>(new
MediaNextButton(isNextEnabled)));
this.isNextEnabled = isNextEnabled;
}
}
catch
{
@@ -113,4 +138,3 @@ public class MediaController :
}
}
}
}
@@ -1,4 +0,0 @@
namespace Hyperbar.Widget.MediaController.Windows;
public record MediaControllerPlaybackStatus(PlaybackStatus Status) :
INotification;
@@ -1,31 +0,0 @@
using CommunityToolkit.Mvvm.Input;
namespace Hyperbar.Widget.MediaController.Windows;
public class MediaControllerPlaybackStatusHandler(IMediator mediator,
IServiceFactory factory) :
INotificationHandler<Changed<MediaControllerPlaybackStatus>>
{
public async Task Handle(Changed<MediaControllerPlaybackStatus> notification,
CancellationToken cancellationToken)
{
if (notification.Value is MediaControllerPlaybackStatus mediaControllerPlaybackInformation)
{
if (mediaControllerPlaybackInformation.Status is PlaybackStatus.Playing)
{
await mediator.PublishAsync(new Replaced<WidgetComponentViewModel>(2, factory.Create<MediaButtonViewModel>(
PlaybackButtonType.Pause, "Pause", "\uE769",
new RelayCommand(async () => await mediator.PublishAsync<Pause>()))), nameof(MediaControllerViewModel),
cancellationToken);
}
if (mediaControllerPlaybackInformation.Status is PlaybackStatus.Paused)
{
await mediator.PublishAsync(new Replaced<WidgetComponentViewModel>(2, factory.Create<MediaButtonViewModel>(
PlaybackButtonType.Pause, "Play", "\uE768",
new RelayCommand(async () => await mediator.PublishAsync<Play>()))), nameof(MediaControllerViewModel),
cancellationToken);
}
}
}
}
@@ -2,6 +2,8 @@
namespace Hyperbar.Widget.MediaController.Windows;
[NotificationHandler(nameof(MediaControllerViewModel))]
public class MediaControllerViewModel :
ObservableCollectionViewModel<WidgetComponentViewModel>,
@@ -16,17 +18,14 @@ public class MediaControllerViewModel :
Add<MediaInformationViewModel>();
Add<MediaButtonViewModel>(PlaybackButtonType.Previous,
"Previous", "\uEB9E",
new RelayCommand(async () => await mediator.PublishAsync<Previous>()));
Add<MediaButtonViewModel<MediaPreviousButton>>(new RelayCommand(async () =>
await mediator.PublishAsync<Request<MediaPrevious>>()));
Add<MediaButtonViewModel>(PlaybackButtonType.Pause,
"Pause", "\uE769",
new RelayCommand(async () => await mediator.PublishAsync<Pause>()));
Add<MediaButtonViewModel<MediaPlayPauseButton>>(new RelayCommand(async () =>
await mediator.PublishAsync<Request<MediaPlayPauseButton>>()));
Add<MediaButtonViewModel>(PlaybackButtonType.Forward,
"Forward", "\uEB9D",
new RelayCommand(async () => await mediator.PublishAsync<Forward>()));
Add<MediaButtonViewModel<MediaNextButton>>(new RelayCommand(async () =>
await mediator.PublishAsync<Request<MediaNext>>()));
}
public ITemplateFactory TemplateFactory { get; set; }
@@ -23,9 +23,10 @@ public class MediaControllerWidget :
.AddHandler<MediaControllerHandler>()
.AddTransient<IFactory<MediaController, MediaControllerViewModel?>, MediaControllerViewModelFactory>()
.AddCache<MediaController, MediaControllerViewModel>()
.AddHandler<MediaControllerPlaybackStatusHandler>()
.AddContentTemplate<MediaControllerViewModel, MediaControllerView>()
.AddContentTemplate<MediaInformationViewModel, MediaInformationView>()
.AddContentTemplate<MediaButtonViewModel, MediaButtonView>();
.AddContentTemplate<MediaButtonViewModel<MediaPreviousButton>, MediaButtonView>()
.AddContentTemplate<MediaButtonViewModel<MediaPlayPauseButton>, MediaButtonView>()
.AddContentTemplate<MediaButtonViewModel<MediaNextButton>, MediaButtonView>();
});
}
@@ -2,6 +2,4 @@
public record MediaInformation(string Title,
string Description,
Stream? ThumbnailSource);
byte[]? Image);
@@ -16,7 +16,7 @@
Grid.Column="0"
Width="40"
Height="40">
<Image Source="{Binding ThumbnailSource, Converter={windows:StreamToImageSourceConverter}}" />
<Image Source="{Binding Image, Converter={windows:StreamToImageSourceConverter}}" />
</Border>
<StackPanel Grid.Column="2">
<TextBlock
@@ -32,7 +32,7 @@
TextWrapping="NoWrap" />
<interactivity:Interaction.Behaviors>
<interactions:EventTriggerBehavior EventName="Loaded">
<interactions:InvokeCommandAction Command="{x:Bind ViewModel.Initialize}" />
<interactions:InvokeCommandAction Command="{x:Bind ViewModel.InitializeCommand}" />
</interactions:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</StackPanel>
@@ -13,7 +13,7 @@ public partial class MediaInformationViewModel(IServiceFactory serviceFactory,
private string? description;
[ObservableProperty]
private Stream? thumbnailSource;
private byte[]? image;
[ObservableProperty]
private string? title;
@@ -25,12 +25,12 @@ public partial class MediaInformationViewModel(IServiceFactory serviceFactory,
{
Title = value.Title;
Description = value.Description;
ThumbnailSource = value.ThumbnailSource;
Image = value.Image;
}
return Task.CompletedTask;
}
public override async Task OnInitializeAsync() =>
public override async Task InitializeAsync() =>
await Mediator.PublishAsync<Request<MediaInformation>>();
}
@@ -1,3 +1,3 @@
namespace Hyperbar.Widget.MediaController.Windows;
public record Play : INotification;
public record MediaNext;
@@ -0,0 +1,4 @@
namespace Hyperbar.Widget.MediaController.Windows;
public record MediaNextButton(bool IsEnabled) :
MediaButton(IsEnabled);
@@ -1,3 +1,3 @@
namespace Hyperbar.Widget.MediaController.Windows;
public record Pause : INotification;
public record MediaPlayPause;
@@ -0,0 +1,4 @@
namespace Hyperbar.Widget.MediaController.Windows;
public record MediaPlayPauseButton(bool IsEnabled) :
MediaButton(IsEnabled);
@@ -1,3 +1,3 @@
namespace Hyperbar.Widget.MediaController.Windows;
public record Forward : INotification;
public record MediaPrevious;
@@ -0,0 +1,5 @@
namespace Hyperbar.Widget.MediaController.Windows;
public record MediaPreviousButton(bool IsEnabled) :
MediaButton(IsEnabled);
@@ -1,9 +0,0 @@
namespace Hyperbar.Widget.MediaController.Windows;
public enum PlaybackButtonType
{
Previous,
Play,
Pause,
Forward
}
@@ -1,11 +0,0 @@
namespace Hyperbar.Widget.MediaController.Windows;
public enum PlaybackStatus
{
Closed,
Opened,
Changing,
Stopped,
Playing,
Paused
}
@@ -8,7 +8,7 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.5.231202003-experimental1" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.5.240124002-experimental2" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26031-preview" />
<PackageReference Include="Microsoft.Xaml.Behaviors.WinUI.Managed" Version="2.0.9" />
</ItemGroup>
@@ -17,7 +17,7 @@
Width="{StaticResource ButtonWidth}"
Height="{StaticResource ButtonHeight}"
Padding="{StaticResource ButtonPadding}"
Command="{Binding Click}"
Command="{Binding InvokeCommand}"
Content="{Binding Icon}"
FontFamily="{StaticResource SymbolThemeFontFamily}"
FontSize="16"
@@ -16,7 +16,7 @@
<SplitButton
Height="{StaticResource ButtonHeight}"
Margin="0,1,0,0"
Command="{Binding Click}"
Command="{Binding InvokeCommand}"
Content="{Binding Icon}"
FontFamily="{StaticResource SymbolThemeFontFamily}"
FontSize="16">
+1 -1
View File
@@ -20,7 +20,7 @@
</ItemsControl.ItemContainerTransitions>
<interactivity:Interaction.Behaviors>
<interactions:EventTriggerBehavior EventName="Loaded">
<interactions:InvokeCommandAction Command="{Binding Initialize}" />
<interactions:InvokeCommandAction Command="{Binding InitializeCommand}" />
</interactions:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</ItemsControl>
+6 -9
View File
@@ -11,14 +11,8 @@ public partial class WidgetButtonViewModel(IServiceFactory serviceFactory,
Guid id,
string? text = null,
string? icon = null,
RelayCommand? command = null) : WidgetComponentViewModel(serviceFactory, mediator, disposer, templateFactory)
RelayCommand? invokeCommand = null) : WidgetComponentViewModel(serviceFactory, mediator, disposer, templateFactory)
{
[ObservableProperty]
private IRelayCommand? click = command;
[ObservableProperty]
private bool enabled;
[ObservableProperty]
private string? icon = icon;
@@ -26,8 +20,11 @@ public partial class WidgetButtonViewModel(IServiceFactory serviceFactory,
private Guid id = id;
[ObservableProperty]
private string? text = text;
private IRelayCommand? invokeCommand = invokeCommand;
[ObservableProperty]
private bool visible;
private bool isEnabled;
[ObservableProperty]
private string? text = text;
}
+1 -1
View File
@@ -29,7 +29,7 @@
<PackageReference Include="CommunityToolkit.WinUI.UI.Controls.Primitives" Version="7.1.2" />
<PackageReference Include="CustomExtensions.WinUI" Version="0.1.10-beta" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.5.231202003-experimental1" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.5.240124002-experimental2" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26031-preview" />
<PackageReference Include="Microsoft.Xaml.Behaviors.WinUI.Managed" Version="2.0.9" />
<Manifest Include="$(ApplicationManifest)" />
+1 -1
View File
@@ -4,7 +4,7 @@ namespace Hyperbar;
public interface IInitialization
{
ICommand Initialize { get; }
ICommand InitializeCommand { get; }
Task InitializeAsync();
}
@@ -1,3 +1,4 @@
namespace Hyperbar;
public interface IObservableCollectionViewModel<TItem>;
public interface IObservableCollectionViewModel<TItem> :
IObservableViewModel;
@@ -0,0 +1,8 @@
using System.Windows.Input;
namespace Hyperbar;
public interface IObservableViewModel
{
ICommand InitializeCommand { get; }
}
@@ -54,7 +54,6 @@ public partial class ObservableCollectionViewModel<TItem> :
mediator.Subscribe(this);
collection.CollectionChanged += OnCollectionChanged;
AddRange(items);
}
@@ -62,8 +61,8 @@ public partial class ObservableCollectionViewModel<TItem> :
public int Count => collection.Count;
public ICommand Initialize =>
new AsyncRelayCommand(InitializeAsync);
public ICommand InitializeCommand =>
new AsyncRelayCommand(CoreInitializeAsync);
bool IList.IsFixedSize => false;
@@ -297,7 +296,7 @@ public partial class ObservableCollectionViewModel<TItem> :
return true;
}
public virtual Task OnInitializeAsync()
public virtual Task InitializeAsync()
{
return Task.CompletedTask;
}
@@ -370,7 +369,7 @@ public partial class ObservableCollectionViewModel<TItem> :
private static bool IsCompatibleObject(object? value) =>
(value is TItem) || (value == null && default(TItem) == null);
public async Task InitializeAsync()
private async Task CoreInitializeAsync()
{
if (isInitialized)
{
@@ -380,8 +379,9 @@ public partial class ObservableCollectionViewModel<TItem> :
isInitialized = true;
await Mediator.PublishAsync<Enumerate<TItem>>();
await OnInitializeAsync();
await InitializeAsync();
}
private void OnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs args) =>
CollectionChanged?.Invoke(this, args);
}