Ресурсы XAML
Ресурс — это объект, который можно повторно использовать в разных местах приложения. Примерами ресурсов являются кисти и стили. В этом обзоре описывается использование ресурсов в XAML. Можно также создать и доступ к ресурсам с помощью кода или попеременно между кодом и XAML. Дополнительные сведения см. в разделе ресурсы и код.
Note
Файлы ресурсов, описанных в этом разделе, отличаются от файлов ресурсов, описанных в ресурса приложения WPF, содержимое и файлы данных и отличаются от внедренных или связанных ресурсов, описанных в управление Ресурсами приложения (.NET).
Использование ресурсов в XAML
В следующем примере определяется SolidColorBrush как ресурс в корневом элементе страницы. Затем ссылается на ресурс и использует его для задания свойства нескольких дочерних элементов, включая Ellipse, TextBlockи Button.
<Page Name="root"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<Page.Resources>
<SolidColorBrush x:Key="MyBrush" Color="Gold"/>
<Style TargetType="Border" x:Key="PageBackground">
<Setter Property="Background" Value="Blue"/>
</Style>
<Style TargetType="TextBlock" x:Key="TitleText">
<Setter Property="Background" Value="Blue"/>
<Setter Property="DockPanel.Dock" Value="Top"/>
<Setter Property="FontSize" Value="18"/>
<Setter Property="Foreground" Value="#4E87D4"/>
<Setter Property="FontFamily" Value="Trebuchet MS"/>
<Setter Property="Margin" Value="0,40,10,10"/>
</Style>
<Style TargetType="TextBlock" x:Key="Label">
<Setter Property="DockPanel.Dock" Value="Right"/>
<Setter Property="FontSize" Value="8"/>
<Setter Property="Foreground" Value="{StaticResource MyBrush}"/>
<Setter Property="FontFamily" Value="Arial"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Margin" Value="0,3,10,0"/>
</Style>
</Page.Resources>
<StackPanel>
<Border Style="{StaticResource PageBackground}">
<DockPanel>
<TextBlock Style="{StaticResource TitleText}">Title</TextBlock>
<TextBlock Style="{StaticResource Label}">Label</TextBlock>
<TextBlock DockPanel.Dock="Top" HorizontalAlignment="Left" FontSize="36" Foreground="{StaticResource MyBrush}" Text="Text" Margin="20" />
<Button DockPanel.Dock="Top" HorizontalAlignment="Left" Height="30" Background="{StaticResource MyBrush}" Margin="40">Button</Button>
<Ellipse DockPanel.Dock="Top" HorizontalAlignment="Left" Width="100" Height="100" Fill="{StaticResource MyBrush}" Margin="40" />
</DockPanel>
</Border>
</StackPanel>
</Page>
Каждый элемент уровня платформы (FrameworkElement или FrameworkContentElement) имеет Resources свойство, которое является свойством, содержит ресурсы (как ResourceDictionary), определяющий ресурс. Вы можете определить ресурсы в любом элементе. Тем не менее, ресурсы, наиболее часто определяются в корневом элементе, который является Page в примере.
Каждый ресурс в словаре ресурсов должен иметь уникальный ключ. При определении ресурсов в разметке, можно назначить уникальный ключ через директивы x: Key. Как правило, ключ является строкой. Однако можно задать его как другой тип объекта с помощью соответствующих расширений разметки. Нестроковые ключи для ресурсов используются в определенных функциональных областях в WPF, в частности в стили, ресурсах компонентов и стилях данных.
После определения ресурса можно ссылаться на ресурс, который должен быть использован для значения свойства, с помощью синтаксиса расширения разметки ресурсов, задающего имя ключа, например:
<Button Background="{StaticResource MyBrush}"/>
<Ellipse Fill="{StaticResource MyBrush}"/>
В предыдущем примере когда XAML загрузчика обрабатывает значение {StaticResource MyBrush}
для Background свойство Button, логика подстановки ресурсов сначала проверяет словарь ресурсов для Button элемент. Если Button нет определения ключа ресурса MyBrush
(это не так, его коллекция ресурсов пуста), затем подстановка проверяет родительский элемент Button, который является Page. Таким образом, при определении ресурса на Page корневой элемент, все элементы в логическом дереве Page можно получить доступ, и можно повторно использовать тот же ресурс для задания значения любого свойства, принимает Type , ресурс представляет. В предыдущем примере, же MyBrush
ресурсов задает два различных свойства: Background из Buttonи Fill из Rectangle.
Статические и динамические ресурсы
Ресурс может использоваться как статический или динамический ресурс. Это делается с помощью расширение разметки StaticResource или расширение разметки DynamicResource. Расширения разметки — это функция XAML переполняться можно указать ссылку на объект с расширением разметки обработки строки атрибута и возврата объекта XAML загрузчика. Дополнительные сведения о поведении расширения разметки, см. в разделе расширения разметки и XAML WPF.
При использовании расширения разметки обычно предоставляют один или несколько параметров в виде строки; они обрабатываются этим расширением разметки, а не в контексте задаваемого свойства. Расширение разметки StaticResource обрабатывает ключ путем поиска значения для этого ключа во всех доступных словарях ресурсов. Это происходит во время загрузки, которая является моментом времени, когда процессу загрузки необходимо присвоить значение свойству, которое принимает ссылку на статический ресурс. Расширение разметки DynamicResource вместо процессы ключ путем создания выражения и это выражение остается необработанным пока приложение фактически выполняется, после чего выражение вычисляется и получается значение.
Приведенные ниже соображения могут повлиять на выбор использования ссылки на статический или динамический ресурс.
Общая схема создания ресурсов для приложения (постранично, в приложении, в свободном XAML, в сборке только ресурсов).
Является ли обновление ресурсов в режиме реального времени частью требований приложения.
Соответствующее поведение подстановки этого ссылочного типа ресурса.
Конкретное свойство или тип ресурса и собственное поведение этих типов.
Статические ресурсы
Ссылки на статические ресурсы лучше всего использовать в указанных ниже случаях.
Когда структура приложения концентрирует большую часть его ресурсов в словарях ресурсов уровня страницы или приложения. Ссылки на статические ресурсы не обрабатываются повторно в зависимости от поведения во время выполнения, например при перезагрузке страницы. Таким образом, можно получить выигрыш в производительности благодаря отсутствию большого количества динамических ссылок на ресурсы, когда согласно структуре ресурсов и приложения в них нет необходимости.
Вы задаете значение свойства, не принадлежащем DependencyObject или Freezable.
При создании словаря ресурсов, который будет скомпилирован в DLL и либо упакован как часть приложения, либо совместно использоваться приложениями.
При создании темы для пользовательского элемента управления и определении ресурсов, используемых в темах. В этом случае обычно не требуется подстановка ссылок на динамические ресурсы. Вместо этого требуется подстановка ссылок на статические ресурсы, чтобы подстановка была прогнозируемой и самодостаточной для темы. При использовании ссылки на динамический ресурс даже ссылка в теме остается необработанной до времени выполнения и есть вероятность того, что при применении темы некоторые локальные элементы переопределят ключ, на который тема пытается сослаться, и локальный элемент окажется перед темой при подстановке. Если такое случится, тема будет работать не так, как ожидалось.
При использовании ресурсов для задания большого количества свойств зависимостей. Свойства зависимостей обладают эффективным кэшированием значений, обеспечиваемым системой свойств, поэтому, если предоставить свойству зависимости значение, которое может быть вычислено во время загрузки, свойству не потребуется проверять пересчитанное выражение и оно сможет вернуть последнее фактическое значение. Этот метод может обеспечить выигрыш в производительности.
Вы хотите изменить основной ресурс для всех объектов-получателей, или вы хотите поддерживать отдельные записываемые экземпляры для каждого объекта-получателя с помощью x: Shared Attribute.
Поведение подстановки статического ресурса
Процесс подстановки ищет запрошенный ключ в словаре ресурсов, определенном элементом, который устанавливает это свойство.
Затем процесс подстановки обходит логическое дерево снизу вверх до родительского элемента и его словаря ресурсов. Это продолжается до тех пор, пока не будет достигнут корневой элемент.
Далее проверяются ресурсы приложения. Ресурсы приложения — это ресурсы в словаре ресурсов, который определяется Application объекта для вашей WPF приложения.
Ссылки на статический ресурс из словаря ресурсов должны указывать на ресурс, уже определенный лексически до ссылки на ресурс. Опережающие ссылки не могут быть разрешены ссылкой на статический ресурс. По этой причине, если используются ссылки на статический ресурс, нужно так разрабатывать структуру словаря ресурсов, чтобы ресурсы, предназначенные для использования ресурсами, определялись в начале каждого соответствующего словаря ресурсов или около него.
Подстановку статических ресурсов можно расширить в темы или в системные ресурсы, но это поддерживается только в том случае, поскольку XAML загрузчик задерживает запрос. Задержка необходима, чтобы тема среды выполнения в момент загрузки страницы правильно применялась к приложению. Однако не рекомендуется использование ссылок на статические ресурсы для ключей, которые существуют только в теме или как системные ресурсы. Это происходит потому, что такие ссылки не будут повторно обработаны при изменении темы пользователем в режиме реального времени. Ссылки на динамические ресурсы более надежны при запросе темы или системных ресурсов. Исключением является случай, когда элемент темы сам запрашивает другой ресурс. Такие ссылки должны быть статическими по причинам, упомянутым выше.
Поведение исключения, если ссылка на статический ресурс не найдена, варьируется. Если ресурс был задержан, то исключение возникнет во время выполнения. Если ресурс не был задержан, исключение возникнет во время загрузки.
Динамические ресурсы
Динамические ресурсы лучше всего подходят для указанных ниже случаев.
Когда значение ресурса зависит от условий, не известных до времени выполнения. Сюда входят системные ресурсы или ресурсы, которые в противном случае задаются пользователем. Например, можно создать значения установщика, которые ссылаются на системные свойства, как представлено SystemColors, SystemFonts, или SystemParameters. Эти значения являются действительно динамическими, так как они в конечном счете берутся из среды выполнения пользователя и операционной системы. Кроме того, возможны темы уровня приложения, которые могут изменяться, когда при доступе к ресурсу уровня страницы также необходимо отследить изменения.
При создании стилей темы или ссылке на них для пользовательского элемента управления.
Когда планируется настроить содержимое ResourceDictionary во время существования приложения.
Когда имеется сложная структура ресурсов с взаимозависимостями, где могут потребоваться опережающие ссылки. Ссылки на статические ресурсы не поддерживают опережающие ссылки, но ссылки на динамические ресурсы поддерживают их, так как ресурс не нужно пересчитывать до времени выполнения, и опережающие ссылки, следовательно, не релевантны.
При ссылке на особенно большой с точки зрения компиляции или рабочего множества ресурс, если он может не использоваться немедленно при загрузке страницы. Ссылки на статические ресурсы всегда загружаются из XAML при загрузке страницы; однако ссылка на динамический ресурс не загружается до фактического использования.
При создании стиля, где значения для метода задания могут браться из других значений, на которые влияют темы или другие пользовательские параметры.
Когда ресурсы применяются к элементам, для которых во время существования приложения может быть изменен порядок наследования в логическом дереве. Изменение родительского элемента также потенциально изменяет область подстановки ресурса, так что, если необходим пересчет ресурса в новой области элемента с измененным порядком наследования, всегда следует использовать ссылку на динамический ресурс.
Поведение подстановки динамического ресурса
Поведение подстановки ресурса для ссылки на динамический ресурс аналогично поведению подстановки в коде при вызове метода FindResource или SetResourceReference.
Процесс подстановки ищет запрошенный ключ в словаре ресурсов, определенном элементом, который устанавливает это свойство.
Затем процесс подстановки обходит логическое дерево снизу вверх до родительского элемента и его словаря ресурсов. Это продолжается до тех пор, пока не будет достигнут корневой элемент.
Далее проверяются ресурсы приложения. Ресурсы приложения — это ресурсы в словаре ресурсов, который определяется Application объекта для вашей WPF приложения.
Для текущей активной темы проверяется словарь ресурсов темы. Если тема изменяется во время выполнения, значение будет повторно вычислено.
Проверяются системные ресурсы.
Поведение исключения (если таковое имеется) варьируется.
Если ресурс был запрошен пользователем FindResource вызова и не найден, возникает исключение.
Если ресурс был запрошен пользователем TryFindResource вызова и не найден, исключение не создается, но возвращаемое значение —
null
. Если задаваемое свойство не принимаетnull
, по-прежнему возможно, что глубже исключение (это зависит от задания отдельного свойства).Если ресурс запрошен по ссылке на динамический ресурс в XAMLи не найден, то поведение зависит от общей системы свойств, но общее поведение таково, как если бы не свойство произошло операции задания на уровне, где существует ресурс. Например, при попытке задать фон для отдельного элемента кнопки с помощью ресурса, который не может быть вычислен, не происходит задания значения, но фактическое значение по-прежнему может быть получено от других членов системы свойств и приоритета значения. Например, значение фона может по-прежнему браться из локально определенного стиля кнопки или из стиля темы. Для свойств, не определенных стилями темы, после неудавшейся попытки обработки ресурса фактическое значение может браться из значения по умолчанию в метаданных свойства.
Ограничения
Для ссылок на динамические ресурсы есть некоторые важные ограничения. Должно выполняться по крайней мере одно из указанных ниже условий.
Задаваемое свойство должно быть свойством на FrameworkElement или FrameworkContentElement. Что свойство должно поддерживаться DependencyProperty.
Задаваемое свойство должно быть свойством на Freezable , предоставляется как значение либо FrameworkElement или FrameworkContentElement свойство, или Setter значение.
Так как задаваемое свойство должно быть DependencyProperty или Freezable свойство, большинство изменений свойств может распространяться на пользовательский Интерфейс, так как изменение свойства (измененное значение динамического ресурса) подтверждается системой свойств. Большинство элементов управления включает логику, которая принудительно создаст новый макет элемента управления, если DependencyProperty изменения и что свойство может повлиять на макет. Однако не все свойства, имеющие расширение разметки DynamicResource качестве их значения, гарантированно предоставляют значение таким образом, что они обновляются в реальном времени в пользовательском Интерфейсе. Функциональные возможности по-прежнему могут отличаться в зависимости от свойства, типа, которому принадлежит свойство, или даже логической структуры приложения.
Стили, DataTemplates и неявные ключи
Ранее было отмечено, что все товары в ResourceDictionary потребуется ключ. Тем не менее, это означает, что все ресурсы должны иметь явный x:Key
. Некоторые типы объектов поддерживают неявный ключ, если он определен как ресурс, где значение ключа связано со значением другого свойства. Это называется неявным ключом, тогда как x:Key
атрибута является явным ключом. Любой неявный ключ можно перезаписать, указав явный ключ.
Одним очень важным сценарием для ресурсов является определение Style. На самом деле Style почти всегда определяется как запись в словаре ресурсов, так как стили наследственным образом предназначены для повторного использования. Дополнительные сведения о стилях см. в разделе Стилизация и использование шаблонов.
С помощью неявного ключа можно создавать стили для элементов управления либо ссылаться на них. Стили темы, определяющие внешний вид элемента управления по умолчанию, используют этот неявный ключ. Неявный ключ с точки зрения запроса представляет Type самого элемента управления. Неявный ключ с точки зрения определения ресурса представляет TargetType стиля. Таким образом, если вы создаете темы для пользовательских элементов управления, стили, которые взаимодействуют с существующими стилями темы, необходимо указать директивы x: Key для этого Style. А если требуется использовать стили из тем, то вообще не нужно задавать стиль. Например, следующее определение стиля работает, даже если Style ресурсов не имеет ключа:
<Style TargetType="Button">
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush>
<GradientStop Offset="0.0" Color="AliceBlue"/>
<GradientStop Offset="1.0" Color="Salmon"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="FontSize" Value="18"/>
</Style>
Что стиля на самом деле есть ключ: неявный ключ typeof(
Button)
. В разметке, можно указать TargetType непосредственно в качестве типа имени (или при необходимости можно использовать {x: Type...} для возврата Type.
Через механизмах стилей темы по умолчанию, используемые WPF, что стиль будет применен как стиль среды выполнения для Button на странице, несмотря на то что Button сам пытается задать его Style свойство или конкретного ресурса ссылка на стиль. Стиль, определенный на странице, находится в последовательности подстановки, чем стиль словаря темы, используя тот же ключ, который имеет стиль словаря темы. Вы можете просто указать <Button>Hello</Button>
в любом месте страницы и стиль, определенный с помощью TargetType из Button
будет применен к этой кнопке. Если требуется, можно по-прежнему явно ключ стиля с тем же значением типа, как TargetTypeдля ясности в разметке, но это не является обязательным.
Неявные ключи для стилей не применяются к элементу управления, если OverridesDefaultStyle — true
(также Обратите внимание, что OverridesDefaultStyle может быть задан как часть собственного поведения для класса элемента управления, а не явным образом в экземпляре элемента управления). Кроме того, чтобы поддерживать неявные ключи для производных классов, элемент управления необходимо переопределить DefaultStyleKey (все существующие элементы управления, предоставляемые как часть WPF этого). Дополнительные сведения о стилях, темах и разработке элементов управления см. в разделе рекомендации по разработке элементов.
DataTemplate также имеет неявный ключ. Неявным ключом для DataTemplate является DataType значение свойства. DataType также можно указать как имя типа, а не явным образом с помощью {x: Type...} . Дополнительные сведения см. в разделе Общие сведения о шаблонах данных.