Udostępnij za pośrednictwem


Słowniki zasobów

Interfejs użytkownika aplikacji wieloplatformowej platformy .NET (.NET MAUI) ResourceDictionary to repozytorium zasobów, które są używane przez aplikację .NET MAUI. Typowe zasoby przechowywane w stylach ResourceDictionary , szablonach kontrolek, szablonach danych, konwerterach i kolorach.

Do zasobów XAML przechowywanych w obiekcie ResourceDictionary można odwoływać się i stosować do elementów za pomocą StaticResource rozszerzenia lub DynamicResource znaczników. W języku C# zasoby można również zdefiniować w elemencie , do których ResourceDictionary odwołuje się element, a następnie do których odwołuje się element przy użyciu indeksatora opartego na ciągach.

Napiwek

W programie Visual Studio do projektu można dodać plik oparty na kodzie oparty na ResourceDictionary języku XAML(XAML) do projektu za pomocą szablonu elementu ResourceDictionary (XAML) platformy .NET MAUI.

Tworzenie zasobów

Każdy VisualElement obiekt pochodny ma Resources właściwość , która może ResourceDictionary zawierać zasoby. Application Podobnie obiekt pochodny ma Resources właściwość , która może ResourceDictionary zawierać zasoby.

Aplikacja MAUI platformy .NET może zawierać tylko jedną klasę pochodzącą z Applicationklasy , ale często korzysta z wielu klas, które pochodzą z VisualElementklasy , w tym stron, układów i widoków. Każdy z tych obiektów może mieć właściwość Resources ustawioną ResourceDictionary na zawierające zasoby. Wybieranie miejsca, w którym można zastosować określone ResourceDictionary skutki:

  • Zasoby w obiekcie ResourceDictionary dołączonym do widoku, takiego jak Button lub Label, mogą być stosowane tylko do tego określonego obiektu.
  • Zasoby w dołączonym ResourceDictionary układzie, takim jak StackLayout lub Grid, mogą być stosowane do układu i wszystkich elementów podrzędnych tego układu.
  • Zasoby zdefiniowane ResourceDictionary na poziomie strony można zastosować do strony i do wszystkich jej elementów podrzędnych.
  • ResourceDictionary Zasoby zdefiniowane na poziomie aplikacji można stosować w całej aplikacji.

Z wyjątkiem niejawnych stylów każdy zasób w słowniku zasobów musi mieć unikatowy klucz ciągu zdefiniowany za pomocą atrybutu x:Key .

Poniższy kod XAML przedstawia zasoby zdefiniowane na poziomie ResourceDictionary aplikacji w pliku App.xaml :

<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ResourceDictionaryDemo.App">
    <Application.Resources>

        <Thickness x:Key="PageMargin">20</Thickness>

        <!-- Colors -->
        <Color x:Key="AppBackgroundColor">AliceBlue</Color>
        <Color x:Key="NavigationBarColor">#1976D2</Color>
        <Color x:Key="NavigationBarTextColor">White</Color>
        <Color x:Key="NormalTextColor">Black</Color>

        <!-- Images -->
        <x:String x:Key="BackgroundImage">background</x:String>
        <x:String x:Key="MenuIcon">menu.png</x:String>
        <x:String x:Key="SearchIcon">search.png</x:String>

        <!-- Implicit styles -->
        <Style TargetType="NavigationPage">
            <Setter Property="BarBackgroundColor"
                    Value="{StaticResource NavigationBarColor}" />
            <Setter Property="BarTextColor"
                    Value="{StaticResource NavigationBarTextColor}" />
        </Style>

        <Style TargetType="ContentPage"
               ApplyToDerivedTypes="True">
            <Setter Property="BackgroundColor"
                    Value="{StaticResource AppBackgroundColor}" />
        </Style>

    </Application.Resources>
</Application>

W tym przykładzie słownik zasobów definiuje Thickness zasób, wiele Color zasobów i dwa niejawne Style zasoby.

Ważne

Wstawianie zasobów bezpośrednio między tagami Resources property-element powoduje automatyczne utworzenie ResourceDictionary obiektu. Jednak ważne jest również umieszczenie wszystkich zasobów między opcjonalnymi ResourceDictionary tagami.

Korzystanie z zasobów

Każdy zasób ma klucz określony przy użyciu atrybutu x:Key , który staje się jego kluczem słownika w obiekcie ResourceDictionary. Klucz jest używany do odwołowania się do zasobu z ResourceDictionary StaticResource rozszerzenia znaczników lub DynamicResource XAML.

Rozszerzenie StaticResource znaczników jest podobne do DynamicResource rozszerzenia znaczników, w przypadku którego oba używają klucza słownika do odwołowania się do wartości ze słownika zasobów. Jednak podczas gdy StaticResource rozszerzenie znaczników wykonuje wyszukiwanie pojedynczego słownika, DynamicResource rozszerzenie znaczników utrzymuje link do klucza słownika. W związku z tym, jeśli wpis słownika skojarzony z kluczem zostanie zastąpiony, zmiana zostanie zastosowana do elementu wizualizacji. Umożliwia to wprowadzanie zmian zasobów środowiska uruchomieniowego w aplikacji. Aby uzyskać więcej informacji na temat rozszerzeń znaczników, zobacz Rozszerzenia znaczników XAML.

W poniższym przykładzie XAML pokazano, jak korzystać z zasobów, a także zdefiniować dodatkowy zasób w elemecie StackLayout:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ResourceDictionaryDemo.MainPage"
             Title="Main page">
    <StackLayout Margin="{StaticResource PageMargin}"
                 Spacing="6">
        <StackLayout.Resources>
            <!-- Implicit style -->
            <Style TargetType="Button">
                <Setter Property="FontSize" Value="14" />
                <Setter Property="BackgroundColor" Value="#1976D2" />
                <Setter Property="TextColor" Value="White" />
                <Setter Property="CornerRadius" Value="5" />
            </Style>
        </StackLayout.Resources>

        <Label Text="This app demonstrates consuming resources that have been defined in resource dictionaries." />
        <Button Text="Navigate"
                Clicked="OnNavigateButtonClicked" />
    </StackLayout>
</ContentPage>

W tym przykładzie ContentPage obiekt używa niejawnego stylu zdefiniowanego w słowniku zasobów na poziomie aplikacji. Obiekt StackLayout używa PageMargin zasobu zdefiniowanego w słowniku zasobów na poziomie aplikacji, podczas gdy Button obiekt używa niejawnego stylu zdefiniowanego w słowniku StackLayout zasobów. Spowoduje to wyświetlenie wyglądu pokazanego na poniższym zrzucie ekranu:

Korzystanie z zasobów słownika zasobów.

Ważne

Zasoby specyficzne dla pojedynczej strony nie powinny być uwzględniane w słowniku zasobów na poziomie aplikacji, ponieważ takie zasoby będą analizowane podczas uruchamiania aplikacji, a nie w razie potrzeby przez stronę. Aby uzyskać więcej informacji, zobacz Zmniejszanie rozmiaru słownika zasobów aplikacji.

Zachowanie wyszukiwania zasobów

Następujący proces wyszukiwania występuje, gdy zasób jest przywołyny z StaticResource rozszerzeniem lub DynamicResource znaczników:

  • Żądany klucz jest sprawdzany w słowniku zasobów, jeśli istnieje, dla elementu, który ustawia właściwość. Jeśli żądany klucz zostanie znaleziony, zostanie zwrócona jego wartość, a proces wyszukiwania zakończy się.
  • Jeśli dopasowanie nie zostanie znalezione, proces wyszukiwania przeszukuje drzewo wizualne w górę, sprawdzając słownik zasobów każdego elementu nadrzędnego. Jeśli żądany klucz zostanie znaleziony, zostanie zwrócona jego wartość, a proces wyszukiwania zakończy się. W przeciwnym razie proces będzie kontynuowany w górę do momentu osiągnięcia elementu głównego.
  • Jeśli dopasowanie nie zostanie znalezione w elemecie głównym, zostanie zbadany słownik zasobów na poziomie aplikacji.
  • Jeśli dopasowanie nadal nie zostanie znalezione, zostanie zgłoszony element XamlParseException .

W związku z tym, gdy analizator XAML napotka StaticResource rozszerzenie lub DynamicResource znaczników, wyszukuje pasujący klucz, przechodząc przez drzewo wizualne przy użyciu pierwszego dopasowania, które znajdzie. Jeśli to wyszukiwanie kończy się na stronie i klucz nadal nie został znaleziony, analizator XAML wyszukuje ResourceDictionary dołączony do App obiektu. Jeśli klucz nadal nie zostanie znaleziony, zostanie zgłoszony wyjątek.

Zastępowanie zasobów

Gdy zasoby współużytkują klucze, zasoby zdefiniowane w drzewie wizualizacji będą miały pierwszeństwo przed zdefiniowanymi wyżej. Na przykład ustawienie AppBackgroundColor zasobu na AliceBlue poziomie aplikacji zostanie zastąpione przez zasób na poziomie AppBackgroundColor strony ustawiony na wartość Teal. Podobnie zasób na poziomie AppBackgroundColor strony zostanie zastąpiony przez zasób układu lub poziomu AppBackgroundColor widoku.

Słowniki zasobów autonomicznych

Obiekt ResourceDictionary można również utworzyć jako autonomiczny plik XAML, który nie jest wspierany przez plik za pomocą kodu. Aby utworzyć autonomiczny ResourceDictionaryplik, dodaj nowy ResourceDictionary plik do projektu przy użyciu szablonu elementu ResourceDictionary (XAML) programu .NET MAUI i usuń jego plik za pomocą kodu. Następnie w pliku XAML usuń x:Class atrybut z tagu ResourceDictionary w pobliżu początku pliku. Ponadto dodaj <?xaml-comp compile="true" ?> po nagłówku XML, aby upewnić się, że kod XAML zostanie skompilowany.

Obiekt ResourceDictionary można również utworzyć jako autonomiczny plik XAML, który nie jest wspierany przez plik za pomocą kodu. Aby utworzyć autonomiczny ResourceDictionaryplik, dodaj nowy ResourceDictionary plik do projektu przy użyciu szablonu elementu ResourceDictionary (XAML) programu .NET MAUI i usuń jego plik za pomocą kodu. Następnie w pliku XAML usuń x:Class atrybut z tagu ResourceDictionary w pobliżu początku pliku. Domyślnie autonomiczny ResourceDictionary ma skompilowany kod XAML, chyba że <?xaml-comp compile="false" ?> zostanie określony po nagłówku XML.

Uwaga

ResourceDictionary Autonomiczny musi mieć akcję kompilacji mauiXaml.

Poniższy przykład XAML przedstawia autonomiczną ResourceDictionary nazwę MyResourceDictionary.xaml:

<?xml version="1.0" encoding="UTF-8" ?>
<ResourceDictionary xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
    <DataTemplate x:Key="PersonDataTemplate">
        <ViewCell>
            <Grid RowSpacing="6"
                  ColumnSpacing="6">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="0.5*" />
                    <ColumnDefinition Width="0.2*" />
                    <ColumnDefinition Width="0.3*" />
                </Grid.ColumnDefinitions>
                <Label Text="{Binding Name}"
                       TextColor="{StaticResource NormalTextColor}"
                       FontAttributes="Bold" />
                <Label Grid.Column="1"
                       Text="{Binding Age}"
                       TextColor="{StaticResource NormalTextColor}" />
                <Label Grid.Column="2"
                       Text="{Binding Location}"
                       TextColor="{StaticResource NormalTextColor}"
                       HorizontalTextAlignment="End" />
            </Grid>
        </ViewCell>
    </DataTemplate>
</ResourceDictionary>

W tym przykładzie element ResourceDictionary zawiera pojedynczy zasób, który jest obiektem typu DataTemplate. Plik MyResourceDictionary.xaml może być używany przez scalenie go z innym słownikiem zasobów.

Scal słowniki zasobów

Słowniki zasobów można łączyć, scalając jeden lub więcej ResourceDictionary obiektów do innego ResourceDictionaryobiektu .

Scal słowniki zasobów lokalnych

Plik lokalny ResourceDictionary można scalić z innym ResourceDictionary , tworząc ResourceDictionary obiekt, którego Source właściwość jest ustawiona na nazwę pliku XAML z zasobami:

<ContentPage ...>
    <ContentPage.Resources>
        <!-- Add more resources here -->
        <ResourceDictionary Source="MyResourceDictionary.xaml" />
        <!-- Add more resources here -->
    </ContentPage.Resources>
    ...
</ContentPage>

Ta składnia nie tworzy wystąpienia MyResourceDictionary klasy. Zamiast tego odwołuje się do pliku XAML. Z tego powodu podczas ustawiania Source właściwości plik za kodem nie jest wymagany, a x:Class atrybut można usunąć z tagu głównego pliku MyResourceDictionary.xaml .

Ważne

Właściwość ResourceDictionary.Source można ustawić tylko w języku XAML.

Scalanie słowników zasobów z innych zestawów

Element ResourceDictionary można również scalić z inną, ResourceDictionary dodając ją do MergedDictionaries właściwości ResourceDictionary. Ta technika umożliwia scalanie słowników zasobów niezależnie od zestawu, w którym się znajdują. Scalanie słowników zasobów z zestawów zewnętrznych wymaga ResourceDictionary , aby akcja kompilacji miała ustawioną wartość MauiXaml, aby mieć plik z kodem i zdefiniować x:Class atrybut w tagu głównym pliku.

Ostrzeżenie

Klasa ResourceDictionary definiuje MergedWith również właściwość . Jednak ta właściwość została przestarzała i nie powinna być już używana.

Poniższy przykład kodu przedstawia dwa słowniki zasobów dodawane do MergedDictionaries kolekcji poziomu ResourceDictionarystrony:

<ContentPage ...
             xmlns:local="clr-namespace:ResourceDictionaryDemo"
             xmlns:theme="clr-namespace:MyThemes;assembly=MyThemes">
    <ContentPage.Resources>
        <ResourceDictionary>
            <!-- Add more resources here -->
            <ResourceDictionary.MergedDictionaries>
                <!-- Add more resource dictionaries here -->
                <local:MyResourceDictionary />
                <theme:DefaultTheme />
                <!-- Add more resource dictionaries here -->
            </ResourceDictionary.MergedDictionaries>
            <!-- Add more resources here -->
        </ResourceDictionary>
    </ContentPage.Resources>
    ...
</ContentPage>

W tym przykładzie słownik zasobów z tego samego zestawu i słownik zasobów z zestawu zewnętrznego są scalane ze słownikiem zasobów na poziomie strony. Ponadto można również dodawać inne ResourceDictionary obiekty w MergedDictionaries tagach właściwości-element i inne zasoby poza tymi tagami.

Ważne

W elemecie ResourceDictionarymoże znajdować się tylko jeden MergedDictionaries tag elementu właściwości, ale można umieścić tam tyle ResourceDictionary obiektów, ile jest wymaganych.

Podczas scalania ResourceDictionary zasobów współdzielą identyczne x:Key wartości atrybutów, program .NET MAUI używa następującego pierwszeństwa zasobu:

  1. Zasoby lokalne do słownika zasobów.
  2. Zasoby zawarte w słownikach zasobów, które zostały scalone za pośrednictwem MergedDictionaries kolekcji, w odwrotnej MergedDictionaries kolejności są wymienione we właściwości .

Napiwek

Wyszukiwanie słowników zasobów może być zadaniem intensywnie korzystającym z obliczeń, jeśli aplikacja zawiera wiele dużych słowników zasobów. W związku z tym, aby uniknąć niepotrzebnego wyszukiwania, należy upewnić się, że każda strona w aplikacji używa tylko słowników zasobów odpowiednich dla strony.

Korzystanie ze słownika zasobów opartego na języku XAML na podstawie kodu

Słowniki zasobów zdefiniowane w języku XAML mogą być używane w kodzie, pod warunkiem, że ResourceDictionary element jest wspierany przez plik z kodem. W programie Visual Studio pliki oparte na ResourceDictionary języku XAML, które są oparte na kodzie, można dodać do projektu za pomocą szablonu elementu ResourceDictionary (XAML) platformy .NET MAUI:

Zrzut ekranu przedstawiający słowniki zasobów oparte na kodzie.

Słowniki zasobów oparte na języku XAML, które są wspierane przez pliki kodu za pomocą kodu, można następnie używać z języka C#, dodając je do MergedDictionaries kolekcji słownika zasobów:

Resources.MergedDictionaries.Add(new MyMauiApp.Resources.Styles.MyColors());
Resources.MergedDictionaries.Add(new MyMauiApp.Resources.Styles.MyStyles());

Uzyskiwanie dostępu do zasobów według klucza z kodu

Dostęp do zasobów można uzyskać w słowniku zasobów za pomocą kodu dowolnego innego słownika.

W poniższym przykładzie pokazano, jak pobrać i zastosować zasób ze słownika zasobów strony:

// Retrieve the Primary color value which is in the page's resource dictionary
var hasValue = Resources.TryGetValue("Primary", out object primaryColor);

if (hasValue)
{
    myLabel.TextColor = (Color)primaryColor;
}

Jest to zalecane podejście, które gwarantuje, że program .NET MAUI nie zgłosi KeyNotFoundException błędu, jeśli nie będzie mógł pobrać zasobu z kodu. Taka sytuacja może wystąpić, gdy scalony słownik zasobów składa się z zasobów zdefiniowanych w pliku XAML i wbudowanych zasobów. Aby uzyskać więcej informacji, zobacz Problem z usługą GitHub #11214.

Uwaga

Aby pobrać zasoby dla całej aplikacji z kodu, uzyskaj dostęp do słownika App.Current.Resources zasobów.