В моем словаре ресурсов не отображается моя метка - PullRequest
1 голос
/ 24 января 2020

У меня есть приложение 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 не отображается в моем приложении. Я вижу, как мой фон соответствующим образом меняет цвет, но мой контроль над ярлыками просто исчез! Что я делаю неправильно? Большое спасибо заранее!

1 Ответ

0 голосов
/ 24 января 2020

Не добавляйте все ресурсные словари темы с самого начала в 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 и Bru sh:

<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>
...