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 Application
klasy , 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:
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:
- Zasoby lokalne do słownika zasobów.
- Zasoby zawarte w słownikach zasobów, które zostały scalone za pośrednictwem
MergedDictionaries
kolekcji, w odwrotnejMergedDictionaries
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:
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.