Часто ресурсы приложения выносят в отдельные файлы, что позволяет не захламлять исходный код приложения. В WPF мы также можем выносить ресурсы во внешние файлы и подключать их в своих приложениях, а также объединять несколько словарей ресурсов. В этой части мы рассмотрим Подключение внешних ресурсов в WPF.
Файлы ресурсов в WPF
Для примера, воспользуемся приложением из предыдущей части. Напомню, что в этом приложении мы определили ресурс на уровне окна приложения:
<Window.Resources>
<LinearGradientBrush x:Shared="False" x:Key="MyBrush">
<GradientStopCollection>
<GradientStop Color="DarkRed" Offset="0"></GradientStop>
<GradientStop Color="Red" Offset="0.5"></GradientStop>
<GradientStop Color="LightPink" Offset="1"></GradientStop>
</GradientStopCollection>
</LinearGradientBrush>
</Window.Resources>
Когда ресурсов не много, то можно оставить этот код как есть. Однако, в приложениях могут быть десятки, а то и сотни различных ресурсов, включая и стили оформления элементов управления из-за чего XAML-код страницы или окна приложения может принять нечитаемый вид. Логично вынести ресурсы во внешний файл (или несколько файлов). Например, создадим в проект новую папку Resources:
Теперь добавим в эту папку новый файл с ресурсами. Для этого можно воспользоваться контекстным меню проекта и выбрать элемент «Словарь ресурсов (WPF)»:
В результате, в наш проект добавиться новый файл, содержащий «скелет» словаря ресурсов:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</ResourceDictionary>
Перенесем в этот файл ресурс из окна приложения:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<LinearGradientBrush x:Shared="False" x:Key="MyBrush">
<GradientStopCollection>
<GradientStop Color="DarkRed" Offset="0"></GradientStop>
<GradientStop Color="Red" Offset="0.5"></GradientStop>
<GradientStop Color="LightPink" Offset="1"></GradientStop>
</GradientStopCollection>
</LinearGradientBrush>
</ResourceDictionary>
При этом, в главном окне кнопка «потеряет» ресурс и станет выглядеть следующим образом:
Чтобы воспользоваться ресурсом из внешнего файла, мы должны воспользоваться подключением файла ресурсов. Рассмотрим подключение файла ресурсов в WPF.
Подключение файла ресурсов
Файлы ресурсов подключаются c использованием ResourceDictionary. Перейдем в файл MainWindow.xaml и изменим его следующим образом:
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<ResourceDictionary Source="/Resources/Res.xaml"/>
</Window.Resources>
<Grid>
<Button Content="Кнопка"
Width="200"
Height="100"
Background="{StaticResource MyBrush}"
Click="Button_Click"/>
</Grid>
</Window>
Обратите внимание на то, как мы подключили внешний файл ресурсов:
<Window.Resources>
<ResourceDictionary Source="/Resources/Res.xaml"/>
</Window.Resources>
Source мы указываем путь к файлу, содержащему словарь ресурсов. Полученные ресурсы мы, в дальнейшем также используем для кнопки. Объединение словарей ресурсов
При необходимости, мы можем объединять различные файлы ресурсов в один словарь. Например, создадим новый файл ресурсов WPF и добавим в него следующий ресурс:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<FontWeight x:Key="ExtraBoldFont">ExtraBold</FontWeight>
</ResourceDictionary>
Теперь у нас есть два словаря ресурсов:
Если мы попытаемся определить оба словаря так, как в примере выше, то получим ошибку:
<Window.Resources>
<ResourceDictionary Source="/Resources/Res.xaml"/>
<ResourceDictionary Source="/Resources/TextStyles.xaml"/>
</Window.Resources>
Поэтому мы должны определить в свойстве Resources только один словарь в котором объединить оба файла. Делается это следующим образом:
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Resources/Res.xaml"/>
<ResourceDictionary Source="/Resources/TextStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
Здесь у нас свойство Resources содержит только один словарь у которого в свойстве MergedDictionaries мы указали два внешних файла с ресурсами для объединения. Теперь мы можем воспользоваться всеми ресурсами из этих файлов, например, так:
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Resources/Res.xaml"/>
<ResourceDictionary Source="/Resources/TextStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<Button Content="Кнопка"
Width="200"
Height="100"
FontWeight="{StaticResource ExtraBoldFont}"
Background="{StaticResource MyBrush}"
Click="Button_Click"/>
</Grid>
</Window>
Теперь свойство Background кнопки будет применяться на основе ресурса из файла Res.xaml, а значение свойства FontWeight браться из ресурса в файле TextStyles.xaml
Итого
При необходимости, мы можем выносить ресурсы WPF в отдельные файлы и подключать их в проект, используя свойство ResourceDictionary.Source. Также, в WPF поддерживается объединение словарей ресурсов как расположенных локально, так и в разных сборках.




