Qual è la differenza tra StaticResource e DynamicResource in WPF?


474

Quando si utilizzano risorse come pennelli, modelli e stili in WPF, possono essere specificati come StaticResources

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

o come DynamicResource

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

Il più delle volte (sempre?), Solo una funziona e l'altra genererà eccezioni durante il runtime. Ma vorrei sapere perché:

  • Qual è la differenza principale. Come le implicazioni di memoria o prestazioni
  • Ci sono regole in WPF come "i pennelli sono sempre statici" e "i modelli sono sempre dinamici" ecc.?

Mi assumo la scelta tra statica e dinamica non è così arbitrario come sembra ... ma non riesco a vedere il modello.


27
È importante notare che gli sviluppatori di app di Windows 8 non hanno DyanmicResource come opzione, ma solo StaticResource.
Jerry Nixon,

2
@Jerry Nixon Grazie a Dio, ho perso il conto del numero di volte in cui non sono riuscito a far funzionare nulla perché stavo usando DynamicResource invece di StaticResource, o viceversa. Dal punto di vista dei programmatori, questa è una complessità non necessaria. Un'analogia è una definizione variabile, dovrei specificare esplicitamente se risiede nell'heap o nello stack? E se sbaglio, si genera un errore di runtime catastrofico?
Contango,

Per una spiegazione più approfondita di StaticResource e DynamicResource e quando utilizzarli, vedere msdn.microsoft.com/en-us/library/ms750613%28v=vs.100%29.aspx .
Michael Repucci,

Risposte:


466

Uno StaticResource verrà risolto e assegnato alla proprietà durante il caricamento di XAML che si verifica prima che l'applicazione venga effettivamente eseguita. Verrà assegnato una sola volta e qualsiasi modifica al dizionario delle risorse verrà ignorata.

Un DynamicResource assegna un oggetto Expression alla proprietà durante il caricamento ma in realtà non cerca la risorsa fino al runtime quando viene richiesto il valore dell'oggetto Expression. Ciò impedisce di cercare la risorsa fino a quando non è necessaria in fase di esecuzione. Un buon esempio potrebbe essere un riferimento diretto a una risorsa definita più avanti in XAML. Un altro esempio è una risorsa che non esisterà nemmeno fino al runtime. Aggiornerà la destinazione se il dizionario delle risorse di origine viene modificato.


4
Cosa deve cambiare prima di utilizzare DynamicResource? Prendi un modello per esempio: lo definisco una volta, ma ovviamente i trigger e le cose possono cambiare il contenuto del modello ma il modello è sempre lo stesso. StaticResource farebbe qui?
Isak Savo,

5
Utilizzare StaticResource se la risorsa a cui ci si collega è definita in XAML prima del suo punto di utilizzo e non cambierà per la durata dell'applicazione in esecuzione. In tal caso, ottieni prestazioni migliori con StaticResource.
Phil Wright,

4
il vincolo a due vie è applicabile su entrambi, se sì quale sarebbe la differenza in quel caso?
WhoIsNinja,

11
L'ultima frase è davvero importante:It will update the target if the source resource dictionary is changed.
MEMark

4
@IsakSavo Considera un'interfaccia utente con temi di colore. Con una risorsa dinamica, puoi scambiare un dizionario con un altro e tutto ciò che fa riferimento alle risorse nel nuovo dizionario verrà aggiornato automaticamente.
Gusdor,

119

Ero anche confuso su di loro. Vedi questo esempio di seguito:

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

Qui ho usato la risorsa dinamica per pulsante e finestra e non l'ho dichiarata da nessuna parte. In fase di runtime, verrà controllato ResourceDictionary della gerarchia. Poiché non l'ho definito, suppongo che verrà utilizzato il valore predefinito.

Se aggiungo il codice qui sotto per fare clic sull'evento di Button, poiché utilizzano DynamicResource, lo sfondo verrà aggiornato di conseguenza.

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

Se avessero usato StaticResource:

  • La risorsa deve essere dichiarata in XAML
  • E anche quello "prima" sono usati.

Spero di aver chiarito un po 'di confusione.


31

StaticResource verrà risolto sulla costruzione dell'oggetto.
DynamicResource verrà valutato e risolto ogni volta che il controllo necessita della risorsa.


21
  1. StaticResource utilizza il primo valore. DynamicResource utilizza l' ultimo valore.
  2. DynamicResource può essere utilizzato per lo stile nidificato, mentre StaticResource no.

Supponiamo di avere questo dizionario di stile nidificato. LightGreen è al livello della radice mentre Pink è nidificato all'interno di una griglia.

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

In 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 renderà il pulsante come LightGreen, il primo valore trovato nello stile. DynamicResource sovrascriverà il pulsante LightGreen su Pink mentre visualizza la griglia.

StaticResource StaticResource

DynamicResource DynamicResource

Tieni presente che VS Designer considera DynamicResource come StaticResource. Otterrà il primo valore. In questo caso, VS Designer renderà il pulsante come LightGreen anche se in realtà diventa Pink.

StaticResource genererà un errore quando viene rimosso lo stile a livello di radice (LightGreen).


13

Qual è la differenza principale. Come le implicazioni di memoria o prestazioni

La differenza tra risorse statiche e dinamiche viene quando cambia l'oggetto sottostante. Se il tuo pennello definito nella raccolta Risorse era accessibile nel codice e impostato su un'istanza di oggetto diversa, Rectangle non rileverà questa modifica.

Risorse statiche recuperate una volta facendo riferimento all'elemento e utilizzate per la durata delle risorse. Considerando che, DynamicResources recupera ogni volta che vengono utilizzati.

L'aspetto negativo delle risorse dinamiche è che tendono a ridurre le prestazioni delle applicazioni.

Ci sono regole in WPF come "i pennelli sono sempre statici" e "i modelli sono sempre dinamici" ecc.?

La migliore pratica è utilizzare le risorse statiche a meno che non vi sia un motivo specifico come se si desidera modificare in modo dinamico la risorsa nel codice. Un altro esempio di esempio in cui si desidera utilizzare risorse dinamiche è quando si utilizzano SystemBrushes, SystenFonts e Parametri di sistema.


7

Trovate tutte le risposte utili, volevo solo aggiungere un altro caso d'uso.

In uno scenario composito WPF, il controllo utente può utilizzare le risorse definite in qualsiasi altra finestra / controllo padre (che ospiterà questo controllo utente) facendo riferimento a tale risorsa come DynamicResource.

Come menzionato da altri, Staticresource verrà consultato al momento della compilazione. I controlli utente non possono fare riferimento a quelle risorse definite nel controllo di hosting / padre. Tuttavia, DynamicResource potrebbe essere utilizzato in questo caso.


3

Importante vantaggio delle risorse dinamiche

se l'avvio dell'applicazione richiede tempi estremamente lunghi, è necessario utilizzare risorse dinamiche, poiché le risorse statiche vengono sempre caricate quando viene creata la finestra o l'app, mentre le risorse dinamiche vengono caricate al primo utilizzo.

Tuttavia, non vedrai alcun vantaggio a meno che la tua risorsa non sia estremamente grande e complessa.


Per DynamicResources, sta creando un problema di prestazioni una sola volta (usato per la prima volta) o ogni volta che viene utilizzato l'elemento?
Morgane,

in questo caso i campi più utilizzati devono essere risorse statiche, i campi personalizzati utilizzati possono essere dinamici, ovvero per le risorse della finestra principale sono statiche e la finestra di dialogo delle risorse può essere dinamica
zamoldar

2

Le risorse dinamiche possono essere utilizzate solo quando la proprietà impostata è sull'oggetto derivato dall'oggetto dipendenza o congelabile dove le risorse statiche possono essere utilizzate ovunque. È possibile sottrarre l'intero controllo utilizzando risorse statiche.

Le risorse statiche vengono utilizzate nelle seguenti circostanze:

  1. Quando la risorsa di reazione cambia in fase di esecuzione non è richiesta.
  2. Se hai bisogno di una buona prestazione con molte risorse.
  3. Facendo riferimento a risorse all'interno dello stesso dizionario.

Risorse dinamiche:

  1. Il valore del tema del setter di proprietà o stile non è noto fino al runtime
    • Ciò include sistema, applicazione, impostazioni basate su temi
    • Ciò include anche riferimenti diretti.
  2. Fare riferimento a risorse di grandi dimensioni che potrebbero non essere caricate durante il caricamento di pagine, finestre, controlli utenti.
  3. Fare riferimento agli stili di tema in un controllo personalizzato.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.