Jaka jest różnica między StaticResource a DynamicResource w WPF?

473

Podczas korzystania z zasobów, takich jak pędzle, szablony i style w WPF, można je określić jako StaticResources

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

lub jako DynamicResource

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

Przez większość czasu (zawsze?) Tylko jedna działa, a druga zgłasza wyjątek podczas działania. Ale chciałbym wiedzieć, dlaczego:

  • Jaka jest główna różnica. Jak implikacje dotyczące pamięci lub wydajności
  • Czy istnieją zasady w WPF, takie jak „pędzle są zawsze statyczne” i „szablony są zawsze dynamiczne” itp.?

I zakładamy, wybór między Static vs dynamiczne nie jest arbitralne, jak się wydaje ... ale nie widzę wzór.

Isak Savo
źródło
27
Należy zauważyć, że programiści aplikacji dla systemu Windows 8 nie mają DyanmicResource jako opcji, tylko StaticResource.
Jerry Nixon
2
@Jerry Nixon Dzięki Bogu za to, straciłem rachubę liczby razy, kiedy nie mogłem nic zrobić, ponieważ korzystałem z DynamicResource zamiast StaticResource lub odwrotnie. Z punktu widzenia programistów jest to niepotrzebna złożoność. Analogią są definicje zmiennych, czy muszę jawnie określać, czy żyje ona na stercie, czy na stosie? A jeśli się pomylę, spowoduje to katastrofalny błąd w czasie wykonywania?
Contango,
Aby uzyskać dokładniejsze objaśnienie StaticResource i DynamicResource, oraz kiedy je stosować, zobacz msdn.microsoft.com/en-us/library/ms750613%28v=vs.100%29.aspx .
Michael Repucci,

Odpowiedzi:

466

StaticResource zostanie rozwiązany i przypisany do właściwości podczas załadunku XAML, który występuje przed aplikacja jest rzeczywiście działać. Zostanie przypisany tylko raz, a wszelkie zmiany w słowniku zasobów zostaną zignorowane.

DynamicResource przypisuje obiekt wyraz mienia podczas załadunku, ale faktycznie nie odnośnika zasobu aż do czasu wykonywania, gdy obiekt zostanie poproszony o wyrażenie wartości. Odracza to wyszukiwanie zasobu, dopóki nie będzie potrzebny w czasie wykonywania. Dobrym przykładem byłoby odniesienie do zasobu zdefiniowanego później w XAML. Innym przykładem jest zasób, który nie będzie istniał aż do czasu wykonania. Zaktualizuje cel, jeśli zmieniony zostanie słownik zasobów źródłowych.

Phil Wright
źródło
4
Co musi się zmienić, zanim będę musiał korzystać z DynamicResource? Weźmy na przykład szablon: definiuję go raz, ale potem oczywiście wyzwalacze i rzeczy mogą zmienić zawartość szablonu, ale szablon jest taki sam. Czy zrobiłby to StaticResource?
Isak Savo
5
Użyj StaticResource, jeśli zasób, do którego się podłączasz, jest zdefiniowany w XAML przed jego użyciem i nie będzie się zmieniał przez cały czas działania aplikacji. W takim przypadku uzyskasz lepszą wydajność dzięki StaticResource.
Phil Wright
4
czy w obu przypadkach obowiązuje zasada „dwa sposoby”, jeśli tak, jaka byłaby różnica w takim przypadku?
WhoIsNinja
11
Ostatnie zdanie jest naprawdę ważne:It will update the target if the source resource dictionary is changed.
UWAGA
4
@ IsakSavo Zastanów się nad interfejsem użytkownika z kolorowymi motywami. Dzięki zasobowi dynamicznemu możesz zamienić jeden słownik na inny, a wszystko, co odnosi się do zasobów w nowym słowniku, zostanie zaktualizowane automatycznie.
Gusdor
119

Byłem także zdezorientowany. Zobacz ten przykład poniżej:

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

Tutaj użyłem zasobu dynamicznego dla przycisku i okna i nie zadeklarowałem go nigdzie. W czasie wykonywania sprawdzany będzie ResourceDictionary hierarchii. Ponieważ go nie zdefiniowałem, domyślnie zostanie użyty.

Jeśli dodam poniższy kod, aby kliknąć zdarzenie Button, ponieważ używają one DynamicResource, tło zostanie odpowiednio zaktualizowane.

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

Jeśli użyli StaticResource:

  • Zasób należy zadeklarować w XAML
  • I to też „przed” są używane.

Mam nadzieję, że usunąłem trochę zamieszania.

Akshay J.
źródło
31

StaticResource zostanie rozwiązany podczas budowy obiektu.
DynamicResource będzie oceniany i rozstrzygany za każdym razem, gdy kontrola potrzebuje zasobu.

Afshin
źródło
21
  1. StaticResource używa pierwszej wartości. DynamicResource używa ostatnio wartości.
  2. DynamicResource może być używany do stylizacji zagnieżdżonej, a StaticResource nie.

Załóżmy, że masz zagnieżdżony słownik stylów. LightGreen znajduje się na poziomie głównym, podczas gdy różowy jest zagnieżdżony w siatce.

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

Z uwagi:

<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 wyświetli przycisk jako LightGreen, pierwszą wartość znalezioną w stylu. DynamicResource zastąpi przycisk LightGreen w kolorze różowym podczas renderowania siatki.

StaticResource StaticResource

DynamicResource DynamicResource

Należy pamiętać, że VS Designer traktuje DynamicResource jako StaticResource. Otrzyma pierwszą wartość. W takim przypadku VS Designer wyrenderuje przycisk jako LightGreen, chociaż w rzeczywistości jest różowy.

StaticResource zgłosi błąd po usunięciu stylu głównego (LightGreen).

Jeson Martajaya
źródło
13

Jaka jest główna różnica. Jak implikacje dotyczące pamięci lub wydajności

Różnica między zasobami statycznymi i dynamicznymi pojawia się, gdy zmienia się obiekt podstawowy. Jeśli dostęp do pędzla zdefiniowanego w kolekcji Zasoby uzyskano w kodzie i ustawiono na inną instancję obiektu, Rectangle nie wykryje tej zmiany.

Zasoby statyczne pobrane raz przez odwołanie do elementu i wykorzystane przez cały okres istnienia zasobów. Natomiast zasoby DynamicResources pobierają za każdym razem, gdy są używane.

Minusem zasobów dynamicznych jest to, że mają one tendencję do zmniejszania wydajności aplikacji.

Czy istnieją zasady w WPF, takie jak „pędzle są zawsze statyczne” i „szablony są zawsze dynamiczne” itp.?

Najlepszą praktyką jest używanie zasobów statycznych, chyba że istnieje konkretny powód, dla którego chcesz dynamicznie zmieniać zasoby w kodzie. Innym przykładem przypadku, w którym chcesz użyć dynamicznych resoruces, jest użycie SystemBrushes, SystenFonts i parametrów systemu.

CharithJ
źródło
7

Uznałem, że wszystkie odpowiedzi są przydatne, chciałem tylko dodać jeszcze jeden przypadek użycia.

W złożonym scenariuszu WPF kontrolka użytkownika może korzystać z zasobów zdefiniowanych w dowolnym innym oknie nadrzędnym / kontrolce (która będzie hostem tej kontroli użytkownika), nazywając ten zasób nazwą DynamicResource.

Jak wspomnieli inni, Staticresource będzie sprawdzany w czasie kompilacji. Kontrola użytkownika nie może odnosić się do zasobów zdefiniowanych w kontroli hosta / kontroli rodzica. Chociaż w tym przypadku można użyć DynamicResource.

Manish Basantani
źródło
3

Ważna zaleta dynamicznych zasobów

jeśli uruchomienie aplikacji zajmuje bardzo dużo czasu, musisz użyć zasobów dynamicznych, ponieważ zasoby statyczne są zawsze ładowane podczas tworzenia okna lub aplikacji, podczas gdy zasoby dynamiczne są ładowane przy pierwszym użyciu.

Jednak nie zobaczysz żadnych korzyści, chyba że twój zasób będzie wyjątkowo duży i złożony.

zamoldar
źródło
W przypadku DynamicResources czy powoduje problem z wydajnością tylko raz (pierwszy raz), czy też za każdym razem, gdy element jest używany?
Morgane
w tym przypadku najczęściej używane pola muszą być zasobami statycznymi, niestandardowe pola mogą być dynamiczne, tj. dla zasobów okna
głównego
2

Z zasobów dynamicznych można korzystać tylko wtedy, gdy ustawiana jest właściwość na obiekcie, który pochodzi z obiektu zależności lub można zamrozić, gdzie jako zasoby statyczne można użyć w dowolnym miejscu. Możesz wyodrębnić całą kontrolę za pomocą zasobów statycznych.

Zasoby statyczne są wykorzystywane w następujących okolicznościach:

  1. Gdy zmiany zasobów reakcji w czasie wykonywania nie są wymagane.
  2. Jeśli potrzebujesz dobrej wydajności z dużą ilością zasobów.
  3. Podczas odwoływania się do zasobów w tym samym słowniku.

Dynamiczne zasoby:

  1. Wartość motywu właściwości lub ustawiacza stylu jest znana dopiero po uruchomieniu
    • Dotyczy to ustawień systemowych, aplikacji i motywów
    • Dotyczy to również referencji do przodu.
  2. Odwoływanie się do dużych zasobów, które mogą się nie ładować, gdy ładuje się strona, system Windows, kontrola użytkownika.
  3. Odwoływanie się do stylów kompozycji w formancie niestandardowym.
iaminvinicble
źródło