WPF StaticResource работает, DynamicResource не работает - PullRequest
9 голосов
/ 21 августа 2010

Я пытался в течение дня безрезультатно создать кучу кистей в теме, а затем использовать их с DynamicResource в пользовательском элементе управления. Что я сделал, это:

  • создать тему generic.xaml, которая содержит стили (работы)
  • добавить словарь для слияния в generic.xaml, содержащий кисти, используемые в приложении (работает)
  • сделать кисти с ключами ComponentResourceKey (работает)
  • сделать управление использованием кисти в качестве статического ресурса (работает)
  • заставить элемент управления использовать кисти в качестве динамического ресурса (НЕ РАБОТАЕТ, источник трассировки ресурса говорит так же: System.Windows.ResourceDictionary Предупреждение: 9: Ресурс не найден;)
  • добавить в App.Resources динамически кисть с тем же ключом (работает с динамическим ресурсом, меняет цвета, не работает со статическим ресурсом, как и ожидалось)

Так что моя проблема в том, что я не могу найти способ определить значения по умолчанию в теме, чтобы я мог программно изменить их в приложении. Как StaticResource может найти кисть, а DynamicResource нет?!

Я должен добавить, что я создал статический класс, содержащий ключи ресурсов компонента в качестве свойств, которые я затем использую в xaml как {x: Static UI: ResourceScheme.ControlBackgroundKey}, например. Моя проблема похожа на эту: ComponentResourceKey как проблема DynamicResource только в том случае, если я заменю статические ключи свойств на разметку XAML для ключа ресурса компонента, она все равно не будет работать.

Может кто-нибудь помочь мне здесь? (

Ответы [ 3 ]

5 голосов
/ 21 августа 2010

Наконец исправили. Похоже, что наличие типа для ключа ресурса компонента в другой сборке вызвало всю проблему. Позвольте мне подвести итог:

  • существует класс ресурсов, который содержит ComponentResourceKeys в качестве статических свойств. Тип, используемый в конструкторе ключей ресурса, является типом этого класса. Это в сборке ресурсов.
  • есть тема для пользовательских элементов управления в другой сборке, сборка Controls, которая определяет некоторые кисти, используя в качестве ключа свойства класса ресурса: {x: Статическое пространство имен: ResourceClass.ResourceKeyProperty}
  • в той же теме, шаблоны для элементов управления используют кисти как динамические ресурсы: {DynamicResource {x: Статическое пространство имен: ResourceClass.ResourceKeyProperty}}
  • есть также приложение, которое использует эти элементы управления и которое динамически добавляет пользовательские кисти в ресурсы приложения. Эти кисти имеют те же клавиши, что и в теме.

Конечный результат для этого:

  • элементы управления изначально не используют кисти
  • элементы управления используют кисти, добавленные в ресурсы приложения
  • элементы управления изначально используют кисти, если в теме используется StaticResource, но затем ресурсы приложения игнорируются

Решением для этого является перемещение класса ресурсов в библиотеку элементов управления.

Поскольку я до сих пор не знаю, почему это происходит, этот вопрос остается открытым, даже если он немного изменился: почему он не работает в первом сценарии?

4 голосов
/ 21 августа 2010

Вот разница,

StaticResource загружается во время загрузки, это означает, что ключ ресурса, который вы используете, должен быть лексически определен перед использованием.

Итак, статический ресурсв случае пользовательского элемента управления должен быть определен только выше определения элемента в том же файле generic.xaml.Так что, если вы поместите свои кисти в другой xaml, он, конечно, не будет работать в случае статического ресурса.

Это причина, если другие ресурсы типа xaml не включены в виде какого-либо импорта ввремя компиляции в одном файле, вы не можете использовать статический ресурс в файле.Это просто означает, что фактический xaml файла / компонента / элемента управления каким-то образом должен содержать фактическую ссылку на статический ресурс, который вы используете.

Теперь я сомневаюсь, почему DynamicResource не будет работать, потому что, вероятно, DynamicResource будет выглядеть тольков приложении (где используется элемент управления) ResourceDictionary, но не generic.xaml.

Я не уверен на 100%, но я чувствую, что если вы определяете пользовательский элемент управления и если вы используете DynamicResource, тогда ваши ресурсы должны находиться в Словаре ресурсов приложения или в родительском контейнере словаря ресурсов вашего элемента управления, но это можетне может быть в generic.xaml.

Поскольку DynamicResource будет искать только ключи в логическом дереве времени выполнения элемента управления, и поэтому может не найти ресурсы, которые находятся в generic.xaml, если файл generic.xaml явно не добавлен вApplication.Resources.

Сводка: StaticResource должен быть доступен лексически, прежде чем в том же файле во время компиляции, ресурсы будут доступны в словаре Application.Resources, он все еще может быть найден в логическом дереве, ново время компиляции только в той же dll или в том же generic.xaml.

DynamicResource должен быть найден в Application.Resources и в логическом дереве элемента управления во время выполнения.

Для получения дополнительной информациипожалуйста, проверьте Обзор ресурсов

1 голос
/ 20 декабря 2015

Я пытался воспроизвести вашу проблему, чтобы проверить несколько теорий, почему она не работает, однако я не смог воспроизвести проблему. Установка, кажется, работает.

Поэтому вместо описания решения я опишу нерабочую настройку репро.

Решение

Целевая структура: 4,6

Проекты

  • Управление
    • ссылки
      • Ресурсы
    • файлы
      • Theme.xaml
  • Ресурсы
    • файлы
      • Keys.cs
  • WpfApplication
    • ссылки
      • Управление
      • Ресурсы
    • файлы

Содержимое файла

Theme.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:r="clr-namespace:Resources;assembly=Resources">
    <Color x:Key="{x:Static r:Keys.PrettyColor}">Red</Color>
    <SolidColorBrush x:Key="{x:Static r:Keys.PrettyBrush}" 
                     Color="{DynamicResource {x:Static r:Keys.PrettyColor}}" />
</ResourceDictionary>

Keys.cs

namespace Resources {
    using System.Windows;

    public static class Keys {
        public static readonly ComponentResourceKey PrettyBrush =
            new ComponentResourceKey(typeof(Keys), Ids.PrettyBrush);

        public static readonly ComponentResourceKey PrettyColor =
            new ComponentResourceKey(typeof(Keys), Ids.PrettyColor);
    }

    public static class Ids {
        public const string PrettyBrush = "PrettyBrush";
        public const string PrettyColor = "PrettyColor";
    }
}

MainWindow.xaml

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:resources="clr-namespace:Resources;assembly=Resources"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/Controls;component/Theme.xaml" />
            </ResourceDictionary.MergedDictionaries>
            <Color x:Key="{x:Static resources:Keys.PrettyColor}">Blue</Color>
        </ResourceDictionary>
    </Window.Resources>
    <Border Background="{DynamicResource {x:Static resources:Keys.PrettyBrush}}" />
</Window>

А для ленивых вот скриншот:

enter image description here

...