何时以编程方式检查 Windows Phone 8.1 中的主题更改

When to programmatically check for theme changes in Windows Phone 8.1

我在 Windows Phone 8.1 应用程序中有一个页面,其中有几个组件应该能够具有三种不同的颜色状态。它们应该是红色、蓝色或当前主题的前景色。

因此,如果我的应用在手机上开始使用深色主题,然后用户退出应用并更改浅色主题,然后再次进入我的应用,我需要立即更改组件有旧主题的前景色。

由于组件应该在不同颜色之间变化(主题的前景色只是其中之一)我无法在 XAML.[=23 中将它们的前景设置为 PhoneForegroundColor =]

我所做的是添加一个 Resuming 事件侦听器来执行此操作:

myTextBlock.Foreground = new SolidColorBrush((Color)Application.Current.Resources["PhoneForegroundColor"]);

但是... Resuming 事件在 Application.Current 的资源更新之前触发,所以我最终得到了与以前相同的颜色。如果用户一次又一次地走出去,它会起作用,因为 Application.Current.Resources["PhoneForegroundColor"] 在上一次 Resuming 事件之后的某个时间点更新了。

问题:我什么时候可以第一次阅读更新的Application.Current.Resources["PhoneForegroundColor"],因为Resuming似乎不​​是正确的地方?

问题: 或者,有没有办法让 myTextBlock 继承另一个组件的 ForegroundColor (CSS-ish),这样我就可以改变 myTextBlock.Foreground 在 Red/Blue/Inherit 之间以编程方式进行,而不必介意在我的应用程序生命周期内更改 Phone 主题?

感谢任何建议!

关于您的第一个问题: "Resume process" 没有正式记录,但我发现了以下内容:

Resume 在 UI 线程上被调用。由于它是一个 void 返回方法,调用者将继续,当它有一个 await 内部。如果您将某些内容编组到 UI 线程中,它将在调度程序队列中,因此在当前任务(恢复)之后 运行。

所以我刚刚做了这个(而且它有效^^):

private async void App_Resuming(object sender, object e)
{

    var x1 = new SolidColorBrush((Color)Application.Current.Resources["PhoneForegroundColor"]);
    Debug.WriteLine(x1?.Color.ToString());

    // Await marshalls back to the ui thread,
    // so it gets put into the dispatcher queue
    // and is run after the resuming has finished.
    await Task.Delay(1);

    var x2 = new SolidColorBrush((Color)Application.Current.Resources["PhoneForegroundColor"]);
    Debug.WriteLine(x2?.Color.ToString());
}

关于你的第二个问题:你可以在你的 app.xaml 中引入一个 "ValueProvider",它注册了 resume 事件并提供了一个依赖项 属性 与当前颜色。

您仍然必须在要使用它的任何 TextBlock 上进行设置,但至少直接在 XAML 中进行设置。这可能也适用于样式,但没有尝试过。

实施示例....

提供商:

public class ColorBindingProvider : DependencyObject
{
    public ColorBindingProvider()
    {
        App.Current.Resuming += App_Resuming;
    }

    private async void App_Resuming(object sender, object e)
    {
        // Delay 1ms (see answer to your first question)
        await Task.Delay(1);

        TextColor = new SolidColorBrush((Color)Application.Current.Resources["PhoneForegroundColor"]);
    }

    public Brush TextColor
    {
        get { return (Brush)GetValue(TextColorProperty); }
        set { SetValue(TextColorProperty, value); }
    }

    public static readonly DependencyProperty TextColorProperty =
        DependencyProperty.Register("TextColor", typeof(Brush), typeof(ColorBindingProvider), new PropertyMetadata(null));
}

App.xaml:

<Application.Resources>
    <local:ColorBindingProvider x:Name="ColorBindingProvider" TextColor="{StaticResource PhoneForegroundBrush}" />
</Application.Resources>

MainPage.xaml:

<TextBlock Text="Hey ho let's go" Foreground="{Binding TextColor, Source={StaticResource ColorBindingProvider}}" />

在 Windows Phone 8.1 中,您可以通过 Application.Current.RequestedTheme 确定所选主题 return 枚举值 Windows.UI.Xaml.ApplicationTheme.

示例:

public static string GetImagePath(){
    // if the background color is black, i want a white image
    if(Application.Current.RequestedTheme == ApplicationTheme.Dark)
        return "ms-appx:///Assets/img_light.jpg";

    // if the background color is white, i want a dark image
    return "ms-appx:///Assets/img_dark.jpg";
}

旁注:您甚至可以使用 Application.Current.RequestedTheme

更改所选主题

更多详情:https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.application.requestedtheme

注册到 App_Resuming 对我不起作用,因为当应用程序未暂停时不会引发此事件。我不得不听 Window.Current.CoreWindow.VisibilityChanged += CoreWindow_VisibilityChanged;

此解决方案不需要 Task.Delay