Update sample and version number
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 33 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 42 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 96 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.0 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.1 KiB |
@@ -1,253 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.System;
|
||||
|
||||
namespace NotificationFlyoutSample
|
||||
{
|
||||
public static class DispatcherQueueExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates whether or not <see cref="DispatcherQueue.HasThreadAccess"/> is available.
|
||||
/// </summary>
|
||||
private static bool IsHasThreadAccessPropertyAvailable => true;
|
||||
|
||||
public static Task EnqueueAsync(this DispatcherQueue dispatcher, Action function, DispatcherQueuePriority priority = DispatcherQueuePriority.Normal)
|
||||
{
|
||||
// Run the function directly when we have thread access.
|
||||
// Also reuse Task.CompletedTask in case of success,
|
||||
// to skip an unnecessary heap allocation for every invocation.
|
||||
if (IsHasThreadAccessPropertyAvailable && dispatcher.HasThreadAccess)
|
||||
{
|
||||
try
|
||||
{
|
||||
function();
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return Task.FromException(e);
|
||||
}
|
||||
}
|
||||
|
||||
static Task TryEnqueueAsync(DispatcherQueue dispatcher, Action function, DispatcherQueuePriority priority)
|
||||
{
|
||||
var taskCompletionSource = new TaskCompletionSource<object?>();
|
||||
|
||||
if (!dispatcher.TryEnqueue(priority, () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
function();
|
||||
|
||||
taskCompletionSource.SetResult(null);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
taskCompletionSource.SetException(e);
|
||||
}
|
||||
}))
|
||||
{
|
||||
taskCompletionSource.SetException(GetEnqueueException("Failed to enqueue the operation"));
|
||||
}
|
||||
|
||||
return taskCompletionSource.Task;
|
||||
}
|
||||
|
||||
return TryEnqueueAsync(dispatcher, function, priority);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes a given function on the target <see cref="DispatcherQueue"/> and returns a
|
||||
/// <see cref="Task{TResult}"/> that completes when the invocation of the function is completed.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The return type of <paramref name="function"/> to relay through the returned <see cref="Task{TResult}"/>.</typeparam>
|
||||
/// <param name="dispatcher">The target <see cref="DispatcherQueue"/> to invoke the code on.</param>
|
||||
/// <param name="function">The <see cref="Func{TResult}"/> to invoke.</param>
|
||||
/// <param name="priority">The priority level for the function to invoke.</param>
|
||||
/// <returns>A <see cref="Task"/> that completes when the invocation of <paramref name="function"/> is over.</returns>
|
||||
/// <remarks>If the current thread has access to <paramref name="dispatcher"/>, <paramref name="function"/> will be invoked directly.</remarks>
|
||||
public static Task<T> EnqueueAsync<T>(this DispatcherQueue dispatcher, Func<T> function, DispatcherQueuePriority priority = DispatcherQueuePriority.Normal)
|
||||
{
|
||||
if (IsHasThreadAccessPropertyAvailable && dispatcher.HasThreadAccess)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Task.FromResult(function());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return Task.FromException<T>(e);
|
||||
}
|
||||
}
|
||||
|
||||
static Task<T> TryEnqueueAsync(DispatcherQueue dispatcher, Func<T> function, DispatcherQueuePriority priority)
|
||||
{
|
||||
var taskCompletionSource = new TaskCompletionSource<T>();
|
||||
|
||||
if (!dispatcher.TryEnqueue(priority, () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
taskCompletionSource.SetResult(function());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
taskCompletionSource.SetException(e);
|
||||
}
|
||||
}))
|
||||
{
|
||||
taskCompletionSource.SetException(GetEnqueueException("Failed to enqueue the operation"));
|
||||
}
|
||||
|
||||
return taskCompletionSource.Task;
|
||||
}
|
||||
|
||||
return TryEnqueueAsync(dispatcher, function, priority);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes a given function on the target <see cref="DispatcherQueue"/> and returns a
|
||||
/// <see cref="Task"/> that acts as a proxy for the one returned by the given function.
|
||||
/// </summary>
|
||||
/// <param name="dispatcher">The target <see cref="DispatcherQueue"/> to invoke the code on.</param>
|
||||
/// <param name="function">The <see cref="Func{TResult}"/> to invoke.</param>
|
||||
/// <param name="priority">The priority level for the function to invoke.</param>
|
||||
/// <returns>A <see cref="Task"/> that acts as a proxy for the one returned by <paramref name="function"/>.</returns>
|
||||
/// <remarks>If the current thread has access to <paramref name="dispatcher"/>, <paramref name="function"/> will be invoked directly.</remarks>
|
||||
public static Task EnqueueAsync(this DispatcherQueue dispatcher, Func<Task> function, DispatcherQueuePriority priority = DispatcherQueuePriority.Normal)
|
||||
{
|
||||
// If we have thread access, we can retrieve the task directly.
|
||||
// We don't use ConfigureAwait(false) in this case, in order
|
||||
// to let the caller continue its execution on the same thread
|
||||
// after awaiting the task returned by this function.
|
||||
if (IsHasThreadAccessPropertyAvailable && dispatcher.HasThreadAccess)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (function() is Task awaitableResult)
|
||||
{
|
||||
return awaitableResult;
|
||||
}
|
||||
|
||||
return Task.FromException(GetEnqueueException("The Task returned by function cannot be null."));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return Task.FromException(e);
|
||||
}
|
||||
}
|
||||
|
||||
static Task TryEnqueueAsync(DispatcherQueue dispatcher, Func<Task> function, DispatcherQueuePriority priority)
|
||||
{
|
||||
var taskCompletionSource = new TaskCompletionSource<object?>();
|
||||
|
||||
if (!dispatcher.TryEnqueue(priority, async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (function() is Task awaitableResult)
|
||||
{
|
||||
await awaitableResult.ConfigureAwait(false);
|
||||
|
||||
taskCompletionSource.SetResult(null);
|
||||
}
|
||||
else
|
||||
{
|
||||
taskCompletionSource.SetException(GetEnqueueException("The Task returned by function cannot be null."));
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
taskCompletionSource.SetException(e);
|
||||
}
|
||||
}))
|
||||
{
|
||||
taskCompletionSource.SetException(GetEnqueueException("Failed to enqueue the operation"));
|
||||
}
|
||||
|
||||
return taskCompletionSource.Task;
|
||||
}
|
||||
|
||||
return TryEnqueueAsync(dispatcher, function, priority);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes a given function on the target <see cref="DispatcherQueue"/> and returns a
|
||||
/// <see cref="Task{TResult}"/> that acts as a proxy for the one returned by the given function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The return type of <paramref name="function"/> to relay through the returned <see cref="Task{TResult}"/>.</typeparam>
|
||||
/// <param name="dispatcher">The target <see cref="DispatcherQueue"/> to invoke the code on.</param>
|
||||
/// <param name="function">The <see cref="Func{TResult}"/> to invoke.</param>
|
||||
/// <param name="priority">The priority level for the function to invoke.</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> that relays the one returned by <paramref name="function"/>.</returns>
|
||||
/// <remarks>If the current thread has access to <paramref name="dispatcher"/>, <paramref name="function"/> will be invoked directly.</remarks>
|
||||
public static Task<T> EnqueueAsync<T>(this DispatcherQueue dispatcher, Func<Task<T>> function, DispatcherQueuePriority priority = DispatcherQueuePriority.Normal)
|
||||
{
|
||||
if (IsHasThreadAccessPropertyAvailable && dispatcher.HasThreadAccess)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (function() is Task<T> awaitableResult)
|
||||
{
|
||||
return awaitableResult;
|
||||
}
|
||||
|
||||
return Task.FromException<T>(GetEnqueueException("The Task returned by function cannot be null."));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return Task.FromException<T>(e);
|
||||
}
|
||||
}
|
||||
|
||||
static Task<T> TryEnqueueAsync(DispatcherQueue dispatcher, Func<Task<T>> function, DispatcherQueuePriority priority)
|
||||
{
|
||||
var taskCompletionSource = new TaskCompletionSource<T>();
|
||||
|
||||
if (!dispatcher.TryEnqueue(priority, async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (function() is Task<T> awaitableResult)
|
||||
{
|
||||
var result = await awaitableResult.ConfigureAwait(false);
|
||||
|
||||
taskCompletionSource.SetResult(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
taskCompletionSource.SetException(GetEnqueueException("The Task returned by function cannot be null."));
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
taskCompletionSource.SetException(e);
|
||||
}
|
||||
}))
|
||||
{
|
||||
taskCompletionSource.SetException(GetEnqueueException("Failed to enqueue the operation"));
|
||||
}
|
||||
|
||||
return taskCompletionSource.Task;
|
||||
}
|
||||
|
||||
return TryEnqueueAsync(dispatcher, function, priority);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="InvalidOperationException"/> to return when an enqueue operation fails.
|
||||
/// </summary>
|
||||
/// <param name="message">The message of the exception.</param>
|
||||
/// <returns>An <see cref="InvalidOperationException"/> with a specified message.</returns>
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static InvalidOperationException GetEnqueueException(string message)
|
||||
{
|
||||
return new InvalidOperationException(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace NotificationFlyoutSample
|
||||
{
|
||||
public interface INavigation
|
||||
{
|
||||
void OnNavigatedTo();
|
||||
}
|
||||
}
|
||||
@@ -119,16 +119,9 @@
|
||||
<Compile Include="App.xaml.cs">
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Class1.cs" />
|
||||
<Compile Include="INavigation.cs" />
|
||||
<Compile Include="NowPlayingPage.xaml.cs">
|
||||
<DependentUpon>NowPlayingPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="NowPlayingPageViewModel.cs" />
|
||||
<Compile Include="ObservableObject.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="NowPlayingFlyout.xaml.cs">
|
||||
<DependentUpon>NowPlayingFlyout.xaml</DependentUpon>
|
||||
<Compile Include="SampleFlyout.xaml.cs">
|
||||
<DependentUpon>SampleFlyout.xaml</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -137,11 +130,6 @@
|
||||
</AppxManifest>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Assets\album.jpg" />
|
||||
<Content Include="Assets\notification-icon-light.png" />
|
||||
<Content Include="Assets\Notification-Icon-Playing-Light.png" />
|
||||
<Content Include="Assets\Notification-Icon-Playing.png" />
|
||||
<Content Include="Assets\notification-icon.png" />
|
||||
<Content Include="Properties\Default.rd.xml" />
|
||||
<Content Include="Assets\LockScreenLogo.scale-200.png" />
|
||||
<Content Include="Assets\SplashScreen.scale-200.png" />
|
||||
@@ -169,14 +157,10 @@
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Include="NowPlayingFlyout.xaml">
|
||||
<Page Include="SampleFlyout.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="NowPlayingPage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\TheXamlGuy.NotificationFlyout.Uwp.UI.Controls\TheXamlGuy.NotificationFlyout.Uwp.UI.Controls.csproj">
|
||||
|
||||
@@ -18,10 +18,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TheXamlGuy.NotificationFlyo
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TheXamlGuy.NotificationFlyout.Wpf.UI.Controls", "..\..\src\TheXamlGuy.NotificationFlyout.Wpf.UI.Controls\TheXamlGuy.NotificationFlyout.Wpf.UI.Controls.csproj", "{0AB1D328-BBB0-434B-965A-48ACDB6CBFB7}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NotificationFlyoutSample.Host", "..\NotificationFlyoutSample.Host\NotificationFlyoutSample.Host.csproj", "{EC9E370A-E28A-483E-8DBA-E1BD56CAA51B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NotificationFlyoutSample", "NotificationFlyoutSample.csproj", "{2057ADE0-C61E-45EE-BB7E-A469FE4D4C41}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NotificationFlyoutSample.Launcher", "..\NotificationFlyoutSample.Launcher\NotificationFlyoutSample.Launcher.csproj", "{DB86CC51-8AA1-46A4-B382-B05DE08E0FF6}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -136,26 +136,6 @@ Global
|
||||
{0AB1D328-BBB0-434B-965A-48ACDB6CBFB7}.Release|x64.Build.0 = Release|x64
|
||||
{0AB1D328-BBB0-434B-965A-48ACDB6CBFB7}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{0AB1D328-BBB0-434B-965A-48ACDB6CBFB7}.Release|x86.Build.0 = Release|Any CPU
|
||||
{EC9E370A-E28A-483E-8DBA-E1BD56CAA51B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EC9E370A-E28A-483E-8DBA-E1BD56CAA51B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EC9E370A-E28A-483E-8DBA-E1BD56CAA51B}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{EC9E370A-E28A-483E-8DBA-E1BD56CAA51B}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{EC9E370A-E28A-483E-8DBA-E1BD56CAA51B}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{EC9E370A-E28A-483E-8DBA-E1BD56CAA51B}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{EC9E370A-E28A-483E-8DBA-E1BD56CAA51B}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{EC9E370A-E28A-483E-8DBA-E1BD56CAA51B}.Debug|x64.Build.0 = Debug|x64
|
||||
{EC9E370A-E28A-483E-8DBA-E1BD56CAA51B}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{EC9E370A-E28A-483E-8DBA-E1BD56CAA51B}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{EC9E370A-E28A-483E-8DBA-E1BD56CAA51B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EC9E370A-E28A-483E-8DBA-E1BD56CAA51B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EC9E370A-E28A-483E-8DBA-E1BD56CAA51B}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{EC9E370A-E28A-483E-8DBA-E1BD56CAA51B}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{EC9E370A-E28A-483E-8DBA-E1BD56CAA51B}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{EC9E370A-E28A-483E-8DBA-E1BD56CAA51B}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{EC9E370A-E28A-483E-8DBA-E1BD56CAA51B}.Release|x64.ActiveCfg = Release|x64
|
||||
{EC9E370A-E28A-483E-8DBA-E1BD56CAA51B}.Release|x64.Build.0 = Release|x64
|
||||
{EC9E370A-E28A-483E-8DBA-E1BD56CAA51B}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{EC9E370A-E28A-483E-8DBA-E1BD56CAA51B}.Release|x86.Build.0 = Release|Any CPU
|
||||
{2057ADE0-C61E-45EE-BB7E-A469FE4D4C41}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||
{2057ADE0-C61E-45EE-BB7E-A469FE4D4C41}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{2057ADE0-C61E-45EE-BB7E-A469FE4D4C41}.Debug|ARM.Build.0 = Debug|ARM
|
||||
@@ -182,6 +162,26 @@ Global
|
||||
{2057ADE0-C61E-45EE-BB7E-A469FE4D4C41}.Release|x86.ActiveCfg = Release|x86
|
||||
{2057ADE0-C61E-45EE-BB7E-A469FE4D4C41}.Release|x86.Build.0 = Release|x86
|
||||
{2057ADE0-C61E-45EE-BB7E-A469FE4D4C41}.Release|x86.Deploy.0 = Release|x86
|
||||
{DB86CC51-8AA1-46A4-B382-B05DE08E0FF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DB86CC51-8AA1-46A4-B382-B05DE08E0FF6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DB86CC51-8AA1-46A4-B382-B05DE08E0FF6}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{DB86CC51-8AA1-46A4-B382-B05DE08E0FF6}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{DB86CC51-8AA1-46A4-B382-B05DE08E0FF6}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{DB86CC51-8AA1-46A4-B382-B05DE08E0FF6}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{DB86CC51-8AA1-46A4-B382-B05DE08E0FF6}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{DB86CC51-8AA1-46A4-B382-B05DE08E0FF6}.Debug|x64.Build.0 = Debug|x64
|
||||
{DB86CC51-8AA1-46A4-B382-B05DE08E0FF6}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{DB86CC51-8AA1-46A4-B382-B05DE08E0FF6}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{DB86CC51-8AA1-46A4-B382-B05DE08E0FF6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DB86CC51-8AA1-46A4-B382-B05DE08E0FF6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DB86CC51-8AA1-46A4-B382-B05DE08E0FF6}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{DB86CC51-8AA1-46A4-B382-B05DE08E0FF6}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{DB86CC51-8AA1-46A4-B382-B05DE08E0FF6}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{DB86CC51-8AA1-46A4-B382-B05DE08E0FF6}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{DB86CC51-8AA1-46A4-B382-B05DE08E0FF6}.Release|x64.ActiveCfg = Release|x64
|
||||
{DB86CC51-8AA1-46A4-B382-B05DE08E0FF6}.Release|x64.Build.0 = Release|x64
|
||||
{DB86CC51-8AA1-46A4-B382-B05DE08E0FF6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{DB86CC51-8AA1-46A4-B382-B05DE08E0FF6}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
<controls:NotificationFlyout
|
||||
x:Class="NotificationFlyoutSample.NowPlayingFlyout"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:TheXamlGuy.NotificationFlyout.Uwp.UI.Controls"
|
||||
xmlns:mux="using:Microsoft.UI.Xaml.Controls"
|
||||
IconSource="/Assets/Notification-Icon-Playing.png"
|
||||
LightIconSource="/Assets/Notification-Icon-Playing-Light.png">
|
||||
<controls:NotificationFlyout.FlyoutPresenterStyle>
|
||||
<Style TargetType="controls:NotificationFlyoutPresenter">
|
||||
<Setter Property="CornerRadius" Value="8" />
|
||||
<Setter Property="Margin" Value="8" />
|
||||
</Style>
|
||||
</controls:NotificationFlyout.FlyoutPresenterStyle>
|
||||
<controls:NotificationFlyout.ContextMenu>
|
||||
<controls:NotificationFlyoutContextMenu>
|
||||
<MenuFlyoutItem Click="OnCloseMenuFlyoutItemClick" Text="Close" />
|
||||
</controls:NotificationFlyoutContextMenu>
|
||||
</controls:NotificationFlyout.ContextMenu>
|
||||
<Frame
|
||||
x:Name="RootFrame"
|
||||
Width="400"
|
||||
Margin="24" />
|
||||
</controls:NotificationFlyout>
|
||||
@@ -1,80 +0,0 @@
|
||||
<Page
|
||||
x:Class="NotificationFlyoutSample.NowPlayingPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="42" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid Grid.Row="0" Margin="0,0,0,4">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Border
|
||||
Grid.Column="0"
|
||||
Width="94"
|
||||
Height="94"
|
||||
Background="Gray"
|
||||
CornerRadius="4">
|
||||
<Image Source="{x:Bind ViewModel.Thumbnail, Mode=OneWay}" Stretch="UniformToFill" />
|
||||
</Border>
|
||||
<StackPanel Grid.Column="1" Margin="12,12,0,0">
|
||||
<TextBlock Style="{StaticResource BaseTextBlockStyle}" Text="{x:Bind ViewModel.Artist, Mode=TwoWay}" />
|
||||
<TextBlock Text="{x:Bind ViewModel.Song, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Slider Grid.Row="1" />
|
||||
<Grid Grid.Row="2">
|
||||
<TextBlock HorizontalAlignment="Left" Text="00:00" />
|
||||
<TextBlock HorizontalAlignment="Right" Text="04:16" />
|
||||
</Grid>
|
||||
<CommandBar
|
||||
Grid.Row="3"
|
||||
HorizontalAlignment="Center"
|
||||
Background="Transparent"
|
||||
DefaultLabelPosition="Collapsed">
|
||||
<AppBarButton
|
||||
Width="48"
|
||||
Click="{x:Bind ViewModel.Previous}"
|
||||
CornerRadius="4"
|
||||
IsCompact="True">
|
||||
<AppBarButton.Icon>
|
||||
<FontIcon Glyph="" />
|
||||
</AppBarButton.Icon>
|
||||
</AppBarButton>
|
||||
<AppBarButton
|
||||
Width="48"
|
||||
Click="{x:Bind ViewModel.Play}"
|
||||
CornerRadius="4"
|
||||
IsCompact="True"
|
||||
Visibility="{x:Bind ViewModel.IsPaused, Mode=OneWay}">
|
||||
<AppBarButton.Icon>
|
||||
<FontIcon Glyph="" />
|
||||
</AppBarButton.Icon>
|
||||
</AppBarButton>
|
||||
<AppBarButton
|
||||
Width="48"
|
||||
Click="{x:Bind ViewModel.Pause}"
|
||||
CornerRadius="4"
|
||||
IsCompact="True"
|
||||
Visibility="{x:Bind ViewModel.IsPlaying, Mode=OneWay}">
|
||||
<AppBarButton.Icon>
|
||||
<FontIcon Glyph="" />
|
||||
</AppBarButton.Icon>
|
||||
</AppBarButton>
|
||||
<AppBarButton
|
||||
Width="48"
|
||||
Click="{x:Bind ViewModel.Next}"
|
||||
CornerRadius="4"
|
||||
IsCompact="True">
|
||||
<AppBarButton.Icon>
|
||||
<FontIcon Glyph="" />
|
||||
</AppBarButton.Icon>
|
||||
</AppBarButton>
|
||||
</CommandBar>
|
||||
</Grid>
|
||||
</Page>
|
||||
@@ -1,29 +0,0 @@
|
||||
using System;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
|
||||
namespace NotificationFlyoutSample
|
||||
{
|
||||
public sealed partial class NowPlayingPage : Page
|
||||
{
|
||||
public NowPlayingPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
ViewModel = new NowPlayingPageViewModel();
|
||||
DataContext = ViewModel;
|
||||
}
|
||||
|
||||
public NowPlayingPageViewModel ViewModel { get; }
|
||||
|
||||
protected override void OnNavigatedTo(NavigationEventArgs args)
|
||||
{
|
||||
if (DataContext is INavigation navigation)
|
||||
{
|
||||
navigation.OnNavigatedTo();
|
||||
}
|
||||
|
||||
base.OnNavigatedTo(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.ApplicationModel.Core;
|
||||
using Windows.Media.Control;
|
||||
using Windows.Storage.Streams;
|
||||
using Windows.System;
|
||||
using Windows.UI.Core;
|
||||
using Windows.UI.Xaml.Media.Imaging;
|
||||
|
||||
namespace NotificationFlyoutSample
|
||||
{
|
||||
|
||||
public class NowPlayingPageViewModel : ObservableObject, INavigation
|
||||
{
|
||||
private string _artist;
|
||||
private bool _isPlaying;
|
||||
private bool _isPaused;
|
||||
private GlobalSystemMediaTransportControlsSession _session;
|
||||
private string _song;
|
||||
private BitmapImage _thumbnail;
|
||||
|
||||
public bool IsPaused
|
||||
{
|
||||
get => _isPaused;
|
||||
set => SetProperty(ref _isPaused, value);
|
||||
}
|
||||
|
||||
public string Artist
|
||||
{
|
||||
get => _artist;
|
||||
set => SetProperty(ref _artist, value);
|
||||
}
|
||||
|
||||
public bool IsPlaying
|
||||
{
|
||||
get => _isPlaying;
|
||||
set => SetProperty(ref _isPlaying, value);
|
||||
}
|
||||
|
||||
public string Song
|
||||
{
|
||||
get => _song;
|
||||
set => SetProperty(ref _song, value);
|
||||
}
|
||||
|
||||
public async Task Next()
|
||||
{
|
||||
await _session.TrySkipNextAsync();
|
||||
}
|
||||
|
||||
DispatcherQueue d;
|
||||
public async void OnNavigatedTo()
|
||||
{
|
||||
d = DispatcherQueue.GetForCurrentThread();
|
||||
|
||||
var sessionManager = await GlobalSystemMediaTransportControlsSessionManager.RequestAsync();
|
||||
_session = sessionManager.GetCurrentSession();
|
||||
if (_session != null)
|
||||
{
|
||||
_session.MediaPropertiesChanged += OnMediaPropertiesChanged;
|
||||
}
|
||||
}
|
||||
|
||||
public BitmapImage Thumbnail
|
||||
{
|
||||
get => _thumbnail;
|
||||
set => SetProperty(ref _thumbnail, value);
|
||||
}
|
||||
|
||||
private async void OnMediaPropertiesChanged(GlobalSystemMediaTransportControlsSession sender, MediaPropertiesChangedEventArgs args)
|
||||
{
|
||||
var mediaProperties = await _session.TryGetMediaPropertiesAsync();
|
||||
|
||||
await d.EnqueueAsync(async () => {
|
||||
Artist = mediaProperties.Artist;
|
||||
|
||||
var foo = mediaProperties.Thumbnail;
|
||||
|
||||
|
||||
if (foo != null)
|
||||
{
|
||||
var f = await foo.OpenReadAsync();
|
||||
var image = new BitmapImage();
|
||||
await image.SetSourceAsync(f);
|
||||
|
||||
Thumbnail = image;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public async Task Pause()
|
||||
{
|
||||
var result = await _session.TryPauseAsync().AsTask().ConfigureAwait(false);
|
||||
if (result)
|
||||
{
|
||||
IsPlaying = false;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Play()
|
||||
{
|
||||
await _session.TryPlayAsync().AsTask().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task Previous()
|
||||
{
|
||||
await _session.TrySkipPreviousAsync().AsTask().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task UpdateNowPlaying()
|
||||
{
|
||||
var playbackInfo = _session.GetPlaybackInfo();
|
||||
var mediaProperties = await _session.TryGetMediaPropertiesAsync();
|
||||
|
||||
Artist = mediaProperties.Artist;
|
||||
Song = mediaProperties.Title;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace NotificationFlyoutSample
|
||||
{
|
||||
public class ObservableObject : INotifyPropertyChanged
|
||||
{
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
public virtual void OnPropertyChanged([CallerMemberName] string propertyName = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
|
||||
protected virtual bool SetProperty<T>(ref T backingStore, T value, [CallerMemberName] string propertyName = "",
|
||||
Action onChanged = null, Func<T, T, bool> validateValue = null)
|
||||
{
|
||||
if (EqualityComparer<T>.Default.Equals(backingStore, value))
|
||||
return false;
|
||||
|
||||
if (validateValue != null && !validateValue(backingStore, value))
|
||||
return false;
|
||||
|
||||
backingStore = value;
|
||||
onChanged?.Invoke();
|
||||
OnPropertyChanged(propertyName);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<controls:NotificationFlyout
|
||||
x:Class="NotificationFlyoutSample.SampleFlyout"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:TheXamlGuy.NotificationFlyout.Uwp.UI.Controls">
|
||||
<Grid Width="400" Height="600">
|
||||
<Button
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Content="Hello World!" />
|
||||
</Grid>
|
||||
</controls:NotificationFlyout>
|
||||
+2
-8
@@ -2,17 +2,11 @@
|
||||
|
||||
namespace NotificationFlyoutSample
|
||||
{
|
||||
public sealed partial class NowPlayingFlyout
|
||||
public sealed partial class SampleFlyout
|
||||
{
|
||||
public NowPlayingFlyout()
|
||||
public SampleFlyout()
|
||||
{
|
||||
InitializeComponent();
|
||||
Opened += OnOpened;
|
||||
}
|
||||
|
||||
private void OnOpened(object sender, object args)
|
||||
{
|
||||
RootFrame.Navigate(typeof(NowPlayingPage));
|
||||
}
|
||||
|
||||
private void OnCloseMenuFlyoutItemClick(object sender, RoutedEventArgs args)
|
||||
Reference in New Issue
Block a user