Skip to content

Commit

Permalink
Demo 加入新建 CoreWindow
Browse files Browse the repository at this point in the history
  • Loading branch information
wherewhere committed Dec 9, 2023
1 parent 69b94d6 commit 78a1be0
Show file tree
Hide file tree
Showing 20 changed files with 974 additions and 341 deletions.
14 changes: 10 additions & 4 deletions MicaDemo/App.xaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
<Application
x:Class="MicaDemo.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converters="using:MicaDemo.Helpers.ValueConverters"
xmlns:local="using:MicaDemo">
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
Expand All @@ -17,7 +15,15 @@
<Setter Property="Background" Value="Transparent" />
<Setter Property="FontFamily" Value="{StaticResource SymbolThemeFontFamily}" />
</Style>
<converters:TypeConverter x:Key="TypeConverter" />
<Style TargetType="Frame">
<Setter Property="ContentTransitions">
<Setter.Value>
<TransitionCollection>
<NavigationThemeTransition />
</TransitionCollection>
</Setter.Value>
</Setter>
</Style>
<FontFamily x:Key="SymbolThemeFontFamily">Segoe Fluent Icons,Segoe MDL2 Assets,Segoe UI Symbol</FontFamily>
</ResourceDictionary>
</Application.Resources>
Expand Down
38 changes: 28 additions & 10 deletions MicaDemo/App.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
using MicaDemo.Helpers;
using MicaDemo.Helpers.Exceptions;
using MicaDemo.Common;
using MicaDemo.Helpers;
using System;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.ApplicationModel.Core;
using Windows.Foundation.Metadata;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media.Animation;
using Windows.UI.Xaml.Navigation;

namespace MicaDemo
Expand Down Expand Up @@ -33,11 +35,17 @@ public App()
/// <param name="e">有关启动请求和过程的详细信息。</param>
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
RegisterExceptionHandlingSynchronizationContext();
if (!isLoaded)
{
RegisterExceptionHandlingSynchronizationContext();
isLoaded = true;
}

Window window = Window.Current;

// 不要在窗口已包含内容时重复应用程序初始化,
// 只需确保窗口处于活动状态
if (!(Window.Current.Content is Frame rootFrame))
if (!(window.Content is Frame rootFrame))
{
CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = true;

Expand All @@ -52,21 +60,29 @@ protected override void OnLaunched(LaunchActivatedEventArgs e)
}

// 将框架放在当前窗口中
Window.Current.Content = rootFrame;
window.Content = rootFrame;

WindowHelper.TrackWindow(window);
ThemeHelper.Initialize(window);
}

if (e.PrelaunchActivated == false)
if (!e.PrelaunchActivated)
{
if (ApiInformation.IsMethodPresent("Windows.ApplicationModel.Core.CoreApplication", "EnablePrelaunch"))
{
CoreApplication.EnablePrelaunch(true);
}

if (rootFrame.Content == null)
{
// 当导航堆栈尚未还原时,导航到第一页,
// 并通过将所需信息作为导航参数传入来配置
// 参数
rootFrame.Navigate(typeof(MainPage), e.Arguments);
rootFrame.Navigate(typeof(MainPage), e.Arguments, new DrillInNavigationTransitionInfo());
}
ThemeHelper.Initialize();

// 确保当前窗口处于活动状态
Window.Current.Activate();
window.Activate();
}
}

Expand Down Expand Up @@ -106,6 +122,8 @@ private void RegisterExceptionHandlingSynchronizationContext()
.UnhandledException += SynchronizationContext_UnhandledException;
}

private void SynchronizationContext_UnhandledException(object sender, Helpers.Exceptions.UnhandledExceptionEventArgs e) => e.Handled = true;
private void SynchronizationContext_UnhandledException(object sender, Common.UnhandledExceptionEventArgs e) => e.Handled = true;

private bool isLoaded;
}
}
45 changes: 45 additions & 0 deletions MicaDemo/Common/Enumerable.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;

namespace MicaDemo.Common
{
public static class Enumerable
{
/// <summary>
/// Performs the specified action on each element of the <see cref="IEnumerable{T}"/>.
/// </summary>
/// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
/// <param name="source"></param>
/// <param name="action">The <see cref="Action{T}"/> delegate to perform on each element of the <see cref="List{T}"/>.</param>
/// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="action"/> is null.</exception>
public static void ForEach<TSource>(this IEnumerable<TSource> source, Action<TSource> action)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}

if (action == null)
{
throw new ArgumentNullException(nameof(action));
}

if (source is List<TSource> list)
{
list.ForEach(action);
}
else if (source is ImmutableList<TSource> immutableList)
{
immutableList.ForEach(action);
}
else
{
foreach (TSource item in source)
{
action(item);
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
using System.Threading;
using Windows.UI.Xaml.Controls;

namespace MicaDemo.Helpers.Exceptions
namespace MicaDemo.Common
{
/// <summary>
/// Wrapper around a standard synchronization context, that catches any unhandled exceptions.
Expand Down
179 changes: 179 additions & 0 deletions MicaDemo/Common/ThreadSwitcher.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Threading;
using Windows.Foundation.Metadata;
using Windows.System;
using Windows.System.Threading;
using Windows.UI.Core;

namespace MicaDemo.Common
{
/// <summary>
/// The interface of helper type for switch thread.
/// </summary>
public interface IThreadSwitcher : INotifyCompletion
{
/// <summary>
/// Gets a value that indicates whether the asynchronous operation has completed.
/// </summary>
bool IsCompleted { get; }

/// <summary>
/// Ends the await on the completed task.
/// </summary>
void GetResult();

/// <summary>
/// Gets an awaiter used to await this <see cref="IThreadSwitcher"/>.
/// </summary>
/// <returns>An awaiter instance.</returns>
IThreadSwitcher GetAwaiter();
}

/// <summary>
/// A helper type for switch thread by <see cref="CoreDispatcher"/>. This type is not intended to be used directly from your code.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public readonly struct CoreDispatcherThreadSwitcher : IThreadSwitcher
{
private readonly CoreDispatcher dispatcher;
private readonly CoreDispatcherPriority priority;

/// <summary>
/// Initializes a new instance of the <see cref="CoreDispatcherThreadSwitcher"/> struct.
/// </summary>
/// <param name="dispatcher">A <see cref="CoreDispatcher"/> whose foreground thread to switch execution to.</param>
/// <param name="priority">Specifies the priority for event dispatch.</param>
public CoreDispatcherThreadSwitcher(CoreDispatcher dispatcher, CoreDispatcherPriority priority = CoreDispatcherPriority.Normal)
{
this.dispatcher = dispatcher;
this.priority = priority;
}

/// <inheritdoc/>
public bool IsCompleted => dispatcher?.HasThreadAccess != false;

/// <inheritdoc/>
public void GetResult() { }

/// <summary>
/// Gets an awaiter used to await this <see cref="CoreDispatcherThreadSwitcher"/>.
/// </summary>
/// <returns>An awaiter instance.</returns>
public CoreDispatcherThreadSwitcher GetAwaiter() => this;

/// <inheritdoc/>
IThreadSwitcher IThreadSwitcher.GetAwaiter() => this;

/// <inheritdoc/>
public void OnCompleted(Action continuation) => _ = dispatcher.RunAsync(priority, () => continuation());
}

/// <summary>
/// A helper type for switch thread by <see cref="DispatcherQueue"/>. This type is not intended to be used directly from your code.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public readonly struct DispatcherQueueThreadSwitcher : IThreadSwitcher
{
private readonly DispatcherQueue dispatcher;
private readonly DispatcherQueuePriority priority;

/// <summary>
/// Initializes a new instance of the <see cref="DispatcherQueueThreadSwitcher"/> struct.
/// </summary>
/// <param name="dispatcher">A <see cref="DispatcherQueue"/> whose foreground thread to switch execution to.</param>
/// <param name="priority">Specifies the priority for event dispatch.</param>
public DispatcherQueueThreadSwitcher(DispatcherQueue dispatcher, DispatcherQueuePriority priority = DispatcherQueuePriority.Normal)
{
this.dispatcher = dispatcher;
this.priority = priority;
}

/// <inheritdoc/>
public bool IsCompleted => !(this.dispatcher is DispatcherQueue dispatcher)
|| (ThreadSwitcher.IsHasThreadAccessPropertyAvailable && dispatcher.HasThreadAccess);

/// <inheritdoc/>
public void GetResult() { }

/// <summary>
/// Gets an awaiter used to await this <see cref="DispatcherQueueThreadSwitcher"/>.
/// </summary>
/// <returns>An awaiter instance.</returns>
public DispatcherQueueThreadSwitcher GetAwaiter() => this;

/// <inheritdoc/>
IThreadSwitcher IThreadSwitcher.GetAwaiter() => this;

/// <inheritdoc/>
public void OnCompleted(Action continuation) => _ = dispatcher.TryEnqueue(priority, () => continuation());
}

/// <summary>
/// A helper type for switch thread by <see cref="ThreadPool"/>. This type is not intended to be used directly from your code.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public readonly struct ThreadPoolThreadSwitcher : IThreadSwitcher
{
private readonly WorkItemPriority priority;

/// <summary>
/// Initializes a new instance of the <see cref="ThreadPoolThreadSwitcher"/> struct.
/// </summary>
/// <param name="priority">Specifies the priority for event dispatch.</param>
public ThreadPoolThreadSwitcher(WorkItemPriority priority = WorkItemPriority.Normal) => this.priority = priority;

/// <inheritdoc/>
public bool IsCompleted => SynchronizationContext.Current == null;

/// <inheritdoc/>
public void GetResult() { }

/// <summary>
/// Gets an awaiter used to await this <see cref="ThreadPoolThreadSwitcher"/>.
/// </summary>
/// <returns>An awaiter instance.</returns>
public ThreadPoolThreadSwitcher GetAwaiter() => this;

/// <inheritdoc/>
IThreadSwitcher IThreadSwitcher.GetAwaiter() => this;

/// <inheritdoc/>
public void OnCompleted(Action continuation) => _ = ThreadPool.RunAsync(_ => continuation(), priority);
}

/// <summary>
/// The extensions for switching threads.
/// </summary>
public static class ThreadSwitcher
{
/// <summary>
/// Gets is <see cref="DispatcherQueue.HasThreadAccess"/> supported.
/// </summary>
public static bool IsHasThreadAccessPropertyAvailable { get; } = ApiInformation.IsMethodPresent("Windows.System.DispatcherQueue", "HasThreadAccess");

/// <summary>
/// A helper function—for use within a coroutine—that you can <see langword="await"/> to switch execution to a specific foreground thread.
/// </summary>
/// <param name="dispatcher">A <see cref="DispatcherQueue"/> whose foreground thread to switch execution to.</param>
/// <param name="priority">Specifies the priority for event dispatch.</param>
/// <returns>An object that you can <see langword="await"/>.</returns>
public static DispatcherQueueThreadSwitcher ResumeForegroundAsync(this DispatcherQueue dispatcher, DispatcherQueuePriority priority = DispatcherQueuePriority.Normal) => new DispatcherQueueThreadSwitcher(dispatcher, priority);

/// <summary>
/// A helper function—for use within a coroutine—that you can <see langword="await"/> to switch execution to a specific foreground thread.
/// </summary>
/// <param name="dispatcher">A <see cref="CoreDispatcher"/> whose foreground thread to switch execution to.</param>
/// <param name="priority">Specifies the priority for event dispatch.</param>
/// <returns>An object that you can <see langword="await"/>.</returns>
public static CoreDispatcherThreadSwitcher ResumeForegroundAsync(this CoreDispatcher dispatcher, CoreDispatcherPriority priority = CoreDispatcherPriority.Normal) => new CoreDispatcherThreadSwitcher(dispatcher, priority);

/// <summary>
/// A helper function—for use within a coroutine—that returns control to the caller, and then immediately resumes execution on a thread pool thread.
/// </summary>
/// <param name="priority">Specifies the priority for event dispatch.</param>
/// <returns>An object that you can <see langword="await"/>.</returns>
public static ThreadPoolThreadSwitcher ResumeBackgroundAsync(WorkItemPriority priority = WorkItemPriority.Normal) => new ThreadPoolThreadSwitcher(priority);
}
}
Loading

0 comments on commit 78a1be0

Please sign in to comment.