При использовании в WPF таких ресурсов, как кисти, шаблоны и стили, их можно указать либо как StaticResources.
<Rectangle Fill = "{StaticResource MyBrush}" />
или как DynamicResource
<ItemsControl ItemTemplate = "{DynamicResource MyItemTemplate}" />
В большинстве случаев (всегда?) Работает только один, а другой выдает исключение во время выполнения. Но хотелось бы знать, почему:
Я предполагать выбор между статическим и динамическим не так уж и произволен, как кажется ... но я не вижу закономерности.
@Jerry Nixon Слава богу, я сбился со счета, сколько раз мне не удавалось заставить что-либо работать, потому что я использовал DynamicResource вместо StaticResource или наоборот. С точки зрения программистов, это ненужная сложность. Аналогия - определения переменных. Должен ли я явно указывать, находится ли он в куче или стеке? И если я ошибаюсь, возникает катастрофическая ошибка времени выполнения?
Для более подробного объяснения StaticResource и DynamicResource, а также когда их использовать, см. msdn.microsoft.com/en-us/library/ms750613%28v=vs.100%29.aspx.





StaticResource будет разрешен и назначен свойству во время загрузки XAML, которая происходит до фактического запуска приложения. Он будет назначен только один раз, и любые изменения в словаре ресурсов игнорируются.
DynamicResource назначает объект Expression свойству во время загрузки, но на самом деле не выполняет поиск ресурса до тех пор, пока у объекта Expression не запрашивается значение. Это откладывает поиск ресурса до тех пор, пока он не понадобится во время выполнения. Хорошим примером может служить прямая ссылка на ресурс, определенный позже в XAML. Другой пример - ресурс, который даже не будет существовать до времени выполнения. Он обновит цель при изменении словаря ресурсов источника.
Что нужно изменить, прежде чем мне понадобится DynamicResource? Возьмем, к примеру, шаблон: я определяю его один раз, но тогда, конечно, триггеры и прочее могут изменить содержимое шаблона, но шаблон остается тем же. Подойдет ли StaticResource здесь?
Используйте StaticResource, если ресурс, к которому вы подключаетесь, определен в XAML до его точки использования и не будет изменяться в течение всего времени существования запущенного приложения. В этом случае вы получите лучшую производительность с помощью StaticResource.
применима ли двухсторонняя привязка к обоим из них, если да, то какая будет разница в этом случае?
Последнее предложение действительно важно: It will update the target if the source resource dictionary is changed.
@IsakSavo. Рассмотрим пользовательский интерфейс с цветовыми темами. С динамическим ресурсом вы можете поменять один словарь на другой, и все, что ссылается на ресурсы в новом словаре, будет обновляться автоматически.
Таким образом, StaticResource подобен константе, а DynamicResource подобен переменной.
StaticResource будет разрешен при строительстве объекта. DynamicResource будет оцениваться и разрешаться каждый раз, когда элемент управления нуждается в ресурсе.
Я тоже был в замешательстве по поводу них. См. Этот пример ниже:
<Window x:Class = "WpfApplicationWPF.CommandsWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
Title = "CommandsWindow" Height = "300" Width = "300">
<StackPanel>
<Button Name = "ButtonNew"
Click = "ButtonNew_Click"
Background = "{DynamicResource PinkBrush}">NEW</Button>
<Image Name = "ImageNew"
Source = "pack://application:,,,/images/winter.jpg"></Image>
</StackPanel>
<Window.Background>
<DynamicResource ResourceKey = "PinkBrush"></DynamicResource>
</Window.Background>
</Window>
Здесь я использовал динамический ресурс для кнопки и окна и нигде не объявлял его. Во время выполнения будет проверяться ResourceDictionary иерархии. Поскольку я не определил его, я предполагаю, что будет использоваться значение по умолчанию.
Если я добавлю приведенный ниже код для события нажатия кнопки Button, поскольку они используют DynamicResource, фон будет соответствующим образом обновлен.
private void ButtonNew_Click(object sender, RoutedEventArgs e)
{
this.Resources.Add( "PinkBrush"
,new SolidColorBrush(SystemColors.DesktopColor)
);
}
Если бы они использовали StaticResource:
Надеюсь, я прояснил некоторую путаницу.
В чем главное отличие. Как последствия для памяти или производительности
Разница между статическими и динамическими ресурсами возникает при изменении базового объекта. Если ваша кисть, определенная в коллекции ресурсов, была доступна в коде и была установлена на другой экземпляр объекта, Rectangle не обнаружит это изменение.
Статические ресурсы извлекаются один раз путем ссылки на элемент и используются в течение всего времени существования ресурсов. Принимая во внимание, что DynamicResources извлекаются каждый раз, когда они используются.
Обратной стороной динамических ресурсов является то, что они снижают производительность приложения.
Есть ли в WPF правила вроде «кисти всегда статичны», «шаблоны всегда динамические» и т. д.?
Лучше всего использовать статические ресурсы, если нет особой причины, например, если вы хотите динамически изменять ресурс в коде. Другой пример, в котором вы хотите использовать динамические ресурсы, включает использование SystemBrushes, SystenFonts и System Parameters.
Нашел все ответы полезными, просто хотел добавить еще один вариант использования.
В составном сценарии WPF ваш пользовательский элемент управления может использовать ресурсы, определенные в любом другом родительском окне / элементе управления (который будет размещать этот пользовательский элемент управления), ссылаясь на этот ресурс как на DynamicResource.
Как упоминалось другими, Staticresource будет просматриваться во время компиляции. Пользовательские элементы управления не могут ссылаться на те ресурсы, которые определены в хостинге / родительском элементе управления. Хотя в этом случае можно использовать DynamicResource.
Важное преимущество динамических ресурсов
если запуск приложения занимает очень много времени, необходимо использовать динамические ресурсы, потому что статические ресурсы всегда загружаются при создании окна или приложения, а динамические ресурсы загружаются при первом использовании.
Однако вы не увидите никакой выгоды, если ваш ресурс не слишком велик и сложный.
Для DynamicResources это создает проблему с производительностью только один раз (используется впервые) или каждый раз, когда используется элемент?
в этом случае наиболее часто используемые поля должны быть статическим ресурсом, пользовательские используемые поля могут быть динамическими, т.е. для главного окна ресурсы статичны, а ресурс диалогового окна может быть динамическим.
Предположим, у вас есть вложенный словарь стилей. LightGreen находится на корневом уровне, а розовый вложен в сетку.
<ResourceDictionary xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType = "{x:Type Grid}">
<Style.Resources>
<Style TargetType = "{x:Type Button}" x:Key = "ConflictButton">
<Setter Property = "Background" Value = "Pink"/>
</Style>
</Style.Resources>
</Style>
<Style TargetType = "{x:Type Button}" x:Key = "ConflictButton">
<Setter Property = "Background" Value = "LightGreen"/>
</Style>
</ResourceDictionary>
С учетом:
<Window x:Class = "WpfStyleDemo.ConflictingStyleWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
Title = "ConflictingStyleWindow" Height = "100" Width = "100">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source = "Styles/ConflictingStyle.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<Button Style = "{DynamicResource ConflictButton}" Content = "Test"/>
</Grid>
</Window>
StaticResource отобразит кнопку как LightGreen, первое значение, найденное в стиле. DynamicResource заменит кнопку LightGreen на розовую при рендеринге сетки.
StaticResource
DynamicResource
Имейте в виду, что VS Designer обрабатывает DynamicResource как StaticResource. Он получит первое значение. В этом случае VS Designer отобразит кнопку как LightGreen, хотя на самом деле она будет розовой.
StaticResource выдаст ошибку при удалении стиля корневого уровня (LightGreen).
Все еще сбивает с толку, как LightGreen находится первым в словаре ресурсов, потому что Pink объявляется первым (как еще один выше). Я предполагаю, что когда xaml ищет стиль, он сначала соответствует «невложенному». Однако было бы полезно краткое объяснение.
Динамические ресурсы могут использоваться только в том случае, если устанавливаемое свойство относится к объекту, который является производным от объекта зависимости или фиксируется, когда статические ресурсы можно использовать где угодно. Вы можете абстрагироваться от всего контроля, используя статические ресурсы.
Статические ресурсы используются в следующих случаях:
Динамические ресурсы:
Важно отметить, что разработчики приложений для Windows 8 не имеют DyanmicResource в качестве опции, только StaticResource.