更新通用Windows App XAML中的资源

阿玛迪斯(Amadeusz Wieczorek)

我需要在Universal Windows App中在运行时更改应用程序的TextBlocks的颜色。

通用Windows应用程序不支持动态资源,并且我一直未成功探索几种不同的方法来更改TextBlock的颜色

<TextBlock Text="Test" Style="{StaticResource MyText}"/>

使用风格

<Style x:Key="MyText" TargetType="TextBlock">
    <Setter Property="Foreground" Value="{StaticResource TextColor}" />
</Style>

我的问题是:如何在运行时更改TextBlock的颜色?

以下是所有尝试更改颜色的尝试:


最初,我遵循本文+视频“动态皮肤化Windows 8应用程序”,并将其存储TextColor在单独的字典文件中,可以将其交换进出MergedDictionaries

  • Day.xaml 包含 <SolidColorBrush x:Key="TextColor" Color="#FFDDEEFF" />
  • Night.xaml 包含 <SolidColorBrush x:Key="TextColor" Color="#FFFFDD99" />

在代码中:

    ResourceDictionary _nightTheme = new ResourceDictionary() { Source = new Uri("ms-appx:///Themes/Night.xaml") };
    ResourceDictionary _baseTheme = new ResourceDictionary() { Source = new Uri("ms-appx:///Themes/MyApp.xaml") };

// OnLaunched - I set a default theme to prevent exceptions
    Application.Current.Resources.MergedDictionaries.Add(_dayTheme);

// Method that changes theme:
        if (NightFall)
        {
            Application.Current.Resources.MergedDictionaries.Remove(_dayTheme);
            Application.Current.Resources.MergedDictionaries.Add(_nightTheme);
        }
        else
        {
            Application.Current.Resources.MergedDictionaries.Remove(_nightTheme);
            Application.Current.Resources.MergedDictionaries.Add(_dayTheme);
        }

当这不起作用时,我认为我需要清除字典:

    ResourceDictionary _baseTheme = new ResourceDictionary() { Source = new Uri("ms-appx:///Themes/MyApp.xaml") };
// Method that changes theme:
        Application.Current.Resources.MergedDictionaries.Clear();
        Application.Current.Resources.MergedDictionaries.Add(_baseTheme);
        if (NightFall)
        {
            Application.Current.Resources.MergedDictionaries.Add(_nightTheme);
        }
        else
        {
            Application.Current.Resources.MergedDictionaries.Add(_dayTheme);
        }

我也尝试用更改字典的方法刷新框架,但无济于事

        var frame = Window.Current.Content as Frame;
        frame.Navigate(frame.Content.GetType());

在另一种尝试中,我尝试在运行时创建字典并对其进行更新

ResourceDictionary _dynamicTheme = new ResourceDictionary();
// OnLaunched
        _dynamicTheme.Add("TextColor", new SolidColorBrush(Windows.UI.Colors.Chocolate));
        Application.Current.Resources.MergedDictionaries.Add(_dynamicTheme);
// Method that changes theme
        _dynamicTheme.Remove("TextColor");
        _dynamicTheme.Add("TextColor", new SolidColorBrush(NightFall ? Windows.UI.Colors.Chocolate : Windows.UI.Colors.Cornsilk));

最终,我意识到也许StaticResource使颜色不可变,所以我决定ThemeResource尝试一下。我修改了主题:

<Style x:Key="MyText" TargetType="TextBlock">
    <Setter Property="Foreground" Value="{ThemeResource MyTextColor}" />
</Style>

Day.xaml

<ResourceDictionary.ThemeDictionaries>
    <ResourceDictionary x:Key="Default">
        <SolidColorBrush x:Key="MyTextColor" Color="#FFDDEEFF" />
    </ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>

Night.xaml

<ResourceDictionary.ThemeDictionaries>
    <ResourceDictionary x:Key="Default">
        <SolidColorBrush x:Key="MyTextColor" Color="#FFFFDD99" />
    </ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>

Application.Current.Resources.MergedDictionaries就像以前的尝试一样,我将方法换入和换出同样,颜色没有变化,即使我假刷新Frame

山姆3D3v

几个月前,我遇到了同样的问题,直到遇到以下博客文章,提出了一个很好的通用解决方案,我才能解决该问题

基本上,您需要做的是:

第一的

添加以下帮助程序Frame类,它将替换您的默认帮助程序Frame

public class ThemeAwareFrame : Frame
{
    private static readonly ThemeProxyClass _themeProxyClass = new ThemeProxyClass();

    public static readonly DependencyProperty AppThemeProperty = DependencyProperty.Register(
        "AppTheme", typeof(ElementTheme), typeof(ThemeAwareFrame), new PropertyMetadata(default(ElementTheme), (d, e) => _themeProxyClass.Theme = (ElementTheme)e.NewValue));


    public ElementTheme AppTheme
    {
        get { return (ElementTheme)GetValue(AppThemeProperty); }
        set { SetValue(AppThemeProperty, value); }
    }

    public ThemeAwareFrame(ElementTheme appTheme)
    {
        var themeBinding = new Binding { Source = _themeProxyClass, Path = new PropertyPath("Theme"), Mode = BindingMode.OneWay };
        SetBinding(RequestedThemeProperty, themeBinding);
        AppTheme = appTheme;

    }
    sealed class ThemeProxyClass : INotifyPropertyChanged
    {
        private ElementTheme _theme;

        public ElementTheme Theme
        {
            get { return _theme; }
            set
            {
                _theme = value;
                OnPropertyChanged();
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

ThemeAwareFrame博客文章撰写者解释该类背后的思想是:

我创建一个代理类,该代理类将仅用于存储当前主题,并且,如果更改了主题,则将其传播。这是一个静态字段,因此与所有ThemeAwareFrame共享。

我添加了一个AppTheme依赖项属性。更改后,它将在代理类中更改。

在ThemeAwareFrame构造函数中,我将ThemeRequested属性绑定到代理类Theme属性。

第二

创建您的的主题资源的App.xaml

 <Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary>
                <ResourceDictionary.ThemeDictionaries>
                    <ResourceDictionary x:Key="Dark">
                        <SolidColorBrush x:Key="MyTextColor" Color="DarkGray" />
                    </ResourceDictionary>
                    <ResourceDictionary x:Key="Light">
                        <SolidColorBrush x:Key="MyTextColor" Color="White" />
                    </ResourceDictionary>
                </ResourceDictionary.ThemeDictionaries>
            </ResourceDictionary>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

第三

在App.Xaml.cs中,将rootFrame更改为ThemeAwareFrame而不是简单的Frame:

rootFrame = new ThemeAwareFrame(ElementTheme.Dark);

OnLaunched方法中:

     protected override void OnLaunched(LaunchActivatedEventArgs e)
     {
    #if DEBUG
        if (System.Diagnostics.Debugger.IsAttached)
        {
            this.DebugSettings.EnableFrameRateCounter = true;
        }
    #endif
        Frame rootFrame = Window.Current.Content as Frame;

        // Do not repeat app initialization when the Window already has content,
        // just ensure that the window is active
        if (rootFrame == null)
        {
            // Create a Frame to act as the navigation context and navigate to the first page
            rootFrame = new ThemeAwareFrame(ElementTheme.Dark);
            // TODO: change this value to a cache size that is appropriate for your application
            rootFrame.CacheSize = 1;

            if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
            {
                // TODO: Load state from previously suspended application
            }
     //..

向前

在使用与主题相关的资源时,请使用ThemeResource代替staticResource

<Page.Resources>
    <Style x:Key="MyText" TargetType="TextBlock">
        <Setter Property="Foreground" Value="{ThemeResource MyTextColor}" />
    </Style>
</Page.Resources>

<Grid >
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <TextBlock Text="Test" Style="{StaticResource MyText}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
    <Button Content="Dark Theme" Click="ChangeThemeToDarkClick" Grid.Row="1"></Button>
    <Button Content="Light Theme" Click="ChangeThemeToLightClick" Grid.Row="2"></Button>
</Grid>

最后

要更改您的应用主题,只需更改AppThemerootFrame属性,如下所示:

   private void ChangeThemeToLightClick(object sender, RoutedEventArgs e)
    {
        (Window.Current.Content as ThemeAwareFrame).AppTheme = ElementTheme.Light;
    }

    private void ChangeThemeToDarkClick(object sender, RoutedEventArgs e)
    {
        (Window.Current.Content as ThemeAwareFrame).AppTheme = ElementTheme.Dark;
    }

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

通用Windows App中的Webview

如何从 Xamarin Forms 的 ContentPage 保存 App.xaml 中的资源?

UWP Windows 10 App中页面/视图的通用基类

如何在单个App.xaml中合并不同的资源?

如何在 C# ContentPage 中访问 App.xaml 上的静态资源模板?

在通用Windows App中将AppBar用作多个页面上的资源

XAML-> C#从C#中的资源更新文本属性

Windows 10(通用Windows App)数据验证

通用Windows Phone 8.1应用程序中的App.Current.Host哪里去了?

如何在C#UWA(通用Windows App)中从文件读取和写入

WinRT在Universal App中使用共享资源xaml文件

在app.xaml wpf中导入多个资源文件

使用情节提要代码从Windows Universal App中的资源字典工作

无法将Xaml中的SelectedIndex =“ 0”设置为ListView(Windows Store App)

在 BizTalk 中更新资源

Winform App中定义WPF资源字典

资源作为 XAML 中的节点

在XAML中处理静态资源

在 XAML 中添加资源引用

Windows Store App中的滑块

Windows Universal App中的DeltaManipulation

如何在通用Windows平台应用程序中更新一个特定的dotnet程序集?

通用Windows App与.NET Framework版本之间的关系

通用Windows App Webview内存泄漏-清除缓存

Windows 8 XAML-存储对象本地资源

如何以编程方式从App.xaml访问资源字符串?

如何在 App.xaml 静态资源中使用嵌套字符串...?

在Windows Phone 8上从App.xaml.cs运行任务

UWP-从不同样式的资源字典中引用StaticResource:无法分配给属性“ Windows.UI.Xaml.ResourceDictionary.Source”