【问题标题】:My resource dictionary is omitting my label from being showed我的资源字典忽略了显示我的标签
【发布时间】:2020-01-24 03:40:43
【问题描述】:

我有一个 wpf 应用程序,我正在搞乱加载主题(浅色和深色),我制作了两个在共享程序集中创建的简单资源字典文件:

深色主题(浅色主题的结构相同,但颜色值不同):

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <SolidColorBrush Color="#FF1E1E1E" x:Key="Background"/>
    <SolidColorBrush x:Key="TextColorBrush" Color="White"/>

    <Style TargetType="TextBlock">
        <Setter Property="Foreground" Value="{StaticResource TextColorBrush}"/>
    </Style>

    <Style TargetType="Grid">
        <Setter Property="Background" Value="{StaticResource Background}"/>
    </Style>
</ResourceDictionary>

在我的主应用程序 App.xaml 中,我引用了我的 2 个主题字典

<Application x:Class="Foo.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/Foo.Core.WPF;component/Resources/Dictionary_DarkTheme.xaml" x:Name="DarkTheme"/>
                <ResourceDictionary Source="pack://application:,,,/Foo.Core.WPF;component/Resources/Dictionary_LightTheme.xaml" x:Name="LightTheme"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

根据我选择的主题设置资源的方式在 App.xaml.cs 中完成

public enum Skin { Light, Dark }

    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        public static Skin Skin { get; set; }

        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
            ChangeSkin(Skin.Light);
        }

        public void ChangeSkin(Skin newSkin)
        {
            Skin = newSkin;

            if (Skin == Skin.Dark)
                ApplyResources(Resources.MergedDictionaries[0].Source.ToString());
            else if (Skin == Skin.Light)
                ApplyResources(Resources.MergedDictionaries[1].Source.ToString());
        }

        private void ApplyResources(string src)
        {
            var dict = new ResourceDictionary() { Source = new Uri(src, UriKind.RelativeOrAbsolute) };
            foreach (var mergeDict in dict.MergedDictionaries)
            {
                Resources.MergedDictionaries.Add(mergeDict);
            }

            foreach (var key in dict.Keys)
            {
                Resources[key] = dict[key];
            }
        }
    }

最后,我的主窗口。由于我希望这些特定样式是全局的,因此我没有使用任何键来识别它们。

<Window x:Class="Foo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid>
        <Label Content="hello"/>
    </Grid>
</Window>

但我的主要问题是 Label 控件没有显示在我的应用程序中。我可以看到我的背景颜色发生了适当的变化,但我的标签控件已经消失了!我究竟做错了什么?非常感谢!

【问题讨论】:

    标签: c# wpf resourcedictionary


    【解决方案1】:

    不要将所有主题 ResourceDictionaries 从开头添加到 Application.Resources.MergedDictionaries,即以空 Application.Resources 开头:

    <Application x:Class="Foo.App"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 StartupUri="MainWindow.xaml">
        <Application.Resources>
        </Application.Resources>
    </Application>
    

    然后通过将Application.Current.Resources.MergedDictionaries替换为当前主题来更改主题:

    private void ChangeSkin(Skin skin)
    {
        ResourceDictionary theme = null;
    
        switch (skin)
        {
            case Skin.Light:
                theme = new ResourceDictionary { Source = new Uri("pack://application:,,,/Foo.Core.WPF;component/Resources/Dictionary_LightTheme.xaml") };
                break;
            case Skin.Dark:
                theme = new ResourceDictionary { Source = new Uri("pack://application:,,,/Foo.Core.WPF;component/Resources/Dictionary_DarkTheme.xaml") };
                break;
        }
    
        if (theme != null)
        {
            Application.Current.Resources.MergedDictionaries.Clear();
            Application.Current.Resources.MergedDictionaries.Add(theme);
        }
    }
    

    当更改主题仅意味着替换颜色和画笔时,您还可以将样式移动到 Application.Resources 并在样式设置器中使用 DynamicResource

    <Application x:Class="Foo.App"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 StartupUri="MainWindow.xaml">
        <Application.Resources>
            <Style TargetType="TextBlock">
                <Setter Property="Foreground" Value="{DynamicResource TextColorBrush}"/>
            </Style>
            <Style TargetType="Grid">
                <Setter Property="Background" Value="{DynamicResource Background}"/>
            </Style>
        </Application.Resources>
    </Application>
    

    那么您的主题 ResourceDictionaries 将只包含 Color 和 Brush 资源:

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
        <SolidColorBrush Color="#FF1E1E1E" x:Key="Background"/>
        <SolidColorBrush x:Key="TextColorBrush" Color="White"/>
    </ResourceDictionary>
    

    【讨论】:

    • 再次感谢您,我明白您的意思了。我想做的是让解决方案中的其他项目可以访问这些字典。这样,任何新的 WPF 项目都会引用这些字典所在的共享项目,然后它们可以获得相同的“皮肤”。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-20
    • 2011-12-22
    • 2017-12-09
    相关资源
    最近更新 更多