Qual é a diferença entre StaticResource e DynamicResource no WPF?

474

Ao usar recursos como pincéis, modelos e estilos no WPF, eles podem ser especificados como StaticResources

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

ou como DynamicResource

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

Na maioria das vezes (sempre?), Apenas um funciona e o outro gera exceção durante o tempo de execução. Mas eu gostaria de saber por que:

  • Qual é a principal diferença. Como implicações de memória ou desempenho
  • Existem regras no WPF como "pincéis são sempre estáticos" e "modelos são sempre dinâmicos" etc.?

I assumir a escolha entre estática vs dinâmica não é tão arbitrário quanto parece ... mas não consigo ver o padrão.

Isak Savo
fonte
27
É importante observar que os desenvolvedores do Windows 8 App não têm o DyanmicResource como opção, apenas o StaticResource.
Jerry Nixon
2
@Jerry Nixon Graças a Deus por isso, perdi a conta do número de vezes que não consegui fazer nada funcionar porque estava usando DynamicResource em vez de StaticResource, ou vice-versa. Do ponto de vista dos programadores, isso é complexidade desnecessária. Uma analogia são definições de variáveis. Devo precisar especificar explicitamente se ele vive na pilha ou na pilha? E se eu entendi errado, gera um erro de execução catastrófico?
Contango 22/09
Para obter uma explicação mais detalhada sobre StaticResource e DynamicResource, e quando usar cada um, consulte msdn.microsoft.com/en-us/library/ms750613%28v=vs.100%29.aspx .
Michael Repucci

Respostas:

466

Um StaticResource será resolvido e atribuído à propriedade durante o carregamento do XAML, que ocorre antes da execução do aplicativo. Ele será atribuído apenas uma vez e quaisquer alterações no dicionário de recursos serão ignoradas.

Um DynamicResource atribui um objeto Expression à propriedade durante o carregamento, mas na verdade não pesquisa o recurso até o tempo de execução quando o objeto Expression é solicitado pelo valor. Isso adia a procura do recurso até que seja necessário em tempo de execução. Um bom exemplo seria uma referência direta a um recurso definido posteriormente no XAML. Outro exemplo é um recurso que nem existirá até o tempo de execução. Ele atualizará o destino se o dicionário de recursos de origem for alterado.

Phil Wright
fonte
4
O que precisa mudar antes que eu precise usar o DynamicResource? Tomemos um modelo, por exemplo: eu o defino uma vez, mas é claro que os gatilhos e outras coisas podem alterar o conteúdo do modelo, mas o modelo ainda é o mesmo. StaticResource faria aqui?
Isak Savo
5
Use StaticResource se o recurso ao qual você está se conectando estiver definido no XAML antes de seu ponto de uso e não for alterado durante a vida útil do aplicativo em execução. Nesse caso, você obtém melhor desempenho com StaticResource.
Phil Wright
4
a vinculação bidirecional é aplicável a ambos, se sim, qual seria a diferença nesse caso?
WhoIsNinja
11
A última frase é realmente importante:It will update the target if the source resource dictionary is changed.
MEMark
4
@IsakSavo Considere uma interface do usuário com temas de cores. Com um recurso dinâmico, você pode trocar um dicionário por outro e qualquer recurso de referência no novo dicionário será atualizado automaticamente.
Gusdor
119

Eu também estava confuso sobre eles. Veja este exemplo abaixo:

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

Aqui, usei o recurso dinâmico para botão e janela e não o declarei em nenhum lugar. No tempo de execução, o ResourceDictionary da hierarquia será verificado. Como não o defini, acho que o padrão será usado.

Se eu adicionar o código abaixo para clicar no evento de Button, como eles usam DynamicResource, o plano de fundo será atualizado de acordo.

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

Se eles tivessem usado StaticResource:

  • O recurso deve ser declarado em XAML
  • E que também "antes" eles são usados.

Espero ter esclarecido alguma confusão.

Akshay J
fonte
31

StaticResource será resolvido na construção do objeto.
O DynamicResource será avaliado e resolvido toda vez que o controle precisar do recurso.

Afshin
fonte
21
  1. StaticResource usa o primeiro valor. DynamicResource usa o último valor.
  2. DynamicResource pode ser usado para estilos aninhados, StaticResource não.

Suponha que você tenha esse dicionário de estilo aninhado. LightGreen está no nível da raiz, enquanto Pink está aninhado dentro de uma Grade.

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

Em vista:

<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 renderizará o botão como LightGreen, o primeiro valor encontrado no estilo. O DynamicResource substituirá o botão LightGreen como Rosa, pois renderiza a Grade.

StaticResource StaticResource

DynamicResource DynamicResource

Lembre-se de que o VS Designer trata DynamicResource como StaticResource. Obterá o primeiro valor. Nesse caso, o VS Designer renderizará o botão como LightGreen, embora ele realmente acabe como rosa.

StaticResource lançará um erro quando o estilo no nível raiz (LightGreen) for removido.

Jeson Martajaya
fonte
13

Qual é a principal diferença. Como implicações de memória ou desempenho

A diferença entre recursos estáticos e dinâmicos ocorre quando o objeto subjacente é alterado. Se o seu Brush definido na coleção Resources foi acessado no código e definido para uma instância de objeto diferente, o Rectangle não detectará essa alteração.

Recursos estáticos recuperados uma vez pelo elemento de referência e usados ​​durante a vida útil dos recursos. Visto que DynamicResources é recuperado toda vez que são usados.

A desvantagem dos recursos dinâmicos é que eles tendem a diminuir o desempenho do aplicativo.

Existem regras no WPF como "pincéis são sempre estáticos" e "modelos são sempre dinâmicos" etc.?

A melhor prática é usar recursos estáticos, a menos que haja um motivo específico, como você deseja alterar dinamicamente o recurso no código por trás. Outro exemplo de instância em que você deseja usar recursos dinâmicos inclui quando você usa os SystemBrushes, SystenFonts e System Parameters.

CharithJ
fonte
7

Encontrei todas as respostas úteis, só queria adicionar mais um caso de uso.

Em um cenário WPF composto, seu controle de usuário pode usar os recursos definidos em qualquer outra janela / controle pai (que hospedará esse controle de usuário) consultando esse recurso como DynamicResource.

Conforme mencionado por outros, o Staticresource será pesquisado em tempo de compilação. Os controles do usuário não podem se referir aos recursos definidos no controle de hospedagem / pai. No entanto, DynamicResource pode ser usado neste caso.

Manish Basantani
fonte
3

Benefício importante dos recursos dinâmicos

se a inicialização do aplicativo demorar muito, você deverá usar recursos dinâmicos, porque os recursos estáticos sempre são carregados quando a janela ou o aplicativo é criado, enquanto os recursos dinâmicos são carregados quando são usados ​​pela primeira vez.

No entanto, você não verá nenhum benefício, a menos que seu recurso seja extremamente grande e complexo.

zamoldar
fonte
Para DynamicResources, ele está criando um problema de desempenho apenas uma vez (usado pela primeira vez) ou sempre que o elemento é usado?
Morgane 25/05
neste caso campos mais utilizados devem ser recurso estático, campos usados personalizado pode ser dinâmico, ou seja, por recursos mainwindow são estáticos e de recursos janela de diálogo pode ser dinâmico
zamoldar
2

Os recursos dinâmicos podem ser usados ​​apenas quando a propriedade que está sendo configurada está no objeto derivado do objeto de dependência ou congelável, onde os recursos estáticos podem ser usados ​​em qualquer lugar. Você pode abstrair todo o controle usando recursos estáticos.

Os recursos estáticos são usados ​​nas seguintes circunstâncias:

  1. Quando o recurso de reação é alterado no tempo de execução, não é necessário.
  2. Se você precisar de um bom desempenho com muitos recursos.
  3. Ao fazer referência a recursos dentro do mesmo dicionário.

Recursos dinâmicos:

  1. O valor da propriedade ou o tema do configurador de estilos não é conhecido até o tempo de execução
    • Isso inclui configurações de sistema, aplicação e tema
    • Isso também inclui referências futuras.
  2. Referenciando grandes recursos que podem não carregar quando a página, o Windows e o controle do usuário são carregados.
  3. Referenciando estilos de tema em um controle personalizado.
iaminvinicble
fonte