В чем разница между StaticResource и DynamicResource в WPF?

474

При использовании ресурсов, таких как кисти, шаблоны и стили в WPF, они могут быть указаны как StaticResources.

<Rectangle Fill="{StaticResource MyBrush}" />

или как DynamicResource

<ItemsControl ItemTemplate="{DynamicResource MyItemTemplate}"  />

В большинстве случаев (всегда?) Работает только одна, а другая вызывает исключение во время выполнения. Но я хотел бы знать, почему:

  • В чем главное отличие. Как память или производительность влияет
  • Есть ли в WPF такие правила, как «кисти всегда статичны», «шаблоны всегда динамичны» и т. Д.?

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

Исак Саво
источник
27
Важно отметить, что разработчики приложений для Windows 8 не имеют DyanmicResource в качестве опции, только StaticResource.
Джерри Никсон
2
@ Джерри Никсон Слава Богу за это, я потерял счет тому, сколько раз я ничего не мог заставить работать, потому что я использовал DynamicResource вместо StaticResource, или наоборот. С точки зрения программистов, это лишняя сложность. Аналогия с определениями переменных. Должен ли я явно указывать, находится ли он в куче или в стеке? И если я ошибаюсь, это приводит к катастрофической ошибке во время выполнения?
Contango
Для более подробного объяснения StaticResource и DynamicResource и того, когда их использовать, см. Msdn.microsoft.com/en-us/library/ms750613%28v=vs.100%29.aspx .
Майкл Репуччи,

Ответы:

466

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

DynamicResource присваивает объект Expression свойству во время загрузки , но не на самом деле не LookUp ресурса до времени выполнения , когда объект Expression задаются для значения. Это откладывает поиск ресурса, пока он не понадобится во время выполнения. Хорошим примером может служить прямая ссылка на ресурс, определенный позже в XAML. Другим примером является ресурс, который даже не будет существовать до времени выполнения. Это обновит цель, если исходный словарь ресурсов будет изменен.

Фил Райт
источник
4
Что нужно изменить, прежде чем мне нужно использовать DynamicResource? Возьмем, к примеру, шаблон: я определяю его один раз, но тогда, конечно, триггеры и прочее могут изменить содержимое шаблона, но шаблон остается тем же. Будет ли StaticResource делать здесь?
Исак Саво
5
Используйте StaticResource, если ресурс, к которому вы присоединяетесь, определен в XAML до момента его использования и не будет изменяться в течение всего времени работы приложения. В этом случае вы получите лучшую производительность со StaticResource.
Фил Райт,
4
применимо ли двухстороннее связывание к обоим из них, если да, какая разница в этом случае?
WhoIsNinja
11
Последнее предложение действительно важно:It will update the target if the source resource dictionary is changed.
MEMark
4
@IsakSavo Рассмотрим пользовательский интерфейс с цветными темами. С динамическим ресурсом вы можете поменять один словарь на другой, и все, что ссылается на ресурсы в новом словаре, обновится автоматически.
Гусдор
119

Я был также смущен о них. Смотрите этот пример ниже:

<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 иерархии. Так как я не определил его, я думаю, будет использоваться значение по умолчанию.

Если я добавлю приведенный ниже код для события click кнопки, поскольку они используют DynamicResource, фон будет соответствующим образом обновлен.

private void ButtonNew_Click(object sender, RoutedEventArgs e)
{
    this.Resources.Add(  "PinkBrush"
                         ,new SolidColorBrush(SystemColors.DesktopColor)
                       );
}

Если бы они использовали StaticResource:

  • Ресурс должен быть объявлен в XAML
  • И это тоже «до» они используются.

Надеюсь, я прояснил некоторую путаницу.

Акшай Дж
источник
31

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

Afshin
источник
21
  1. StaticResource использует первое значение. DynamicResource использует последнее значение.
  2. DynamicResource может использоваться для вложенных стилей, а StaticResource - нет.

Предположим, у вас есть этот вложенный словарь стилей. LightGreen находится на корневом уровне, в то время как Pink вложен в Grid.

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

DynamicResource DynamicResource

Имейте в виду, что VS Designer рассматривает DynamicResource как StaticResource. Это получит первое значение. В этом случае VS Designer будет отображать кнопку как LightGreen, хотя на самом деле она выглядит как Pink.

StaticResource выдаст ошибку при удалении стиля корневого уровня (LightGreen).

Джесон Мартаджая
источник
13

В чем главное отличие. Как память или производительность влияет

Разница между статическими и динамическими ресурсами возникает при изменении базового объекта. Если ваша кисть, определенная в коллекции ресурсов, была доступна в коде и настроена на другой экземпляр объекта, Rectangle не обнаружит это изменение.

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

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

Есть ли в WPF такие правила, как «кисти всегда статичны», «шаблоны всегда динамичны» и т. Д.?

Лучше всего использовать статические ресурсы, если нет особой причины, например, если вы хотите динамически изменять ресурс в коде. Другой пример, в котором вы хотите использовать динамические ресурсы, включает использование SystemBrushes, SystenFonts и System Parameters.

CharithJ
источник
7

Нашел все ответы полезными, просто хотел добавить еще один вариант использования.

В составном сценарии WPF ваш пользовательский элемент управления может использовать ресурсы, определенные в любом другом родительском окне / элементе управления (который собирается разместить этот пользовательский элемент управления), ссылаясь на этот ресурс как DynamicResource.

Как уже упоминалось, Staticresource будет проверен во время компиляции. Пользовательские элементы управления не могут ссылаться на те ресурсы, которые определены в хостинге / родительском элементе управления. Тем не менее, DynamicResource может быть использован в этом случае.

Маниш Басантани
источник
3

Важное преимущество динамических ресурсов

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

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

zamoldar
источник
Для DynamicResources это создает проблему с производительностью только один раз (используется впервые) или каждый раз, когда используется элемент?
Морган
в этом случае наиболее используемые поля должны быть статическим ресурсом, пользовательские поля могут быть динамическими, т. е. ресурсы
основного
2

Динамические ресурсы могут использоваться только в том случае, если устанавливаемое свойство находится на объекте, который получен из объекта зависимости или может быть заблокирован, когда статические ресурсы могут использоваться где угодно. Вы можете абстрагировать весь контроль, используя статические ресурсы.

Статические ресурсы используются при следующих обстоятельствах:

  1. При изменении ресурса реакции во время выполнения не требуется.
  2. Если вам нужна хорошая производительность с большим количеством ресурсов.
  3. При ссылках на ресурсы в одном словаре.

Динамические ресурсы:

  1. Значение свойства или темы установки стиля не известно до времени выполнения
    • Это включает в себя систему, приложение, настройки на основе темы
    • Это также включает в себя прямые ссылки.
  2. Ссылка на большие ресурсы, которые могут не загружаться при загрузке страницы, окон, пользовательских элементов управления.
  3. Ссылки на стили темы в пользовательском элементе управления.
iaminvinicble
источник