Xamarin.Forms słowniki zasobów
A ResourceDictionary
to repozytorium zasobów, które są używane przez aplikację Xamarin.Forms . Typowe zasoby przechowywane w stylachResourceDictionary
, szablonach kontrolek, szablonach danych, kolorach i konwerterach.
W języku XAML zasoby przechowywane w obiekcie ResourceDictionary
mogą być przywołyne i stosowane do elementów przy użyciu 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. Jednak korzystanie z obiektu ResourceDictionary
w języku C#jest niewielkie, ponieważ obiekty udostępnione można przechowywać jako pola lub właściwości i uzyskiwać do nich dostęp bezpośrednio bez konieczności uprzedniego pobierania ich ze słownika.
Tworzenie zasobów w języku XAML
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 Xamarin.Forms zawiera tylko klasę pochodzącą z Application
klasy , ale często korzysta z wielu klas, które pochodzą z VisualElement
klasy , w tym stron, układów i kontrolek. 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 jakButton
lubLabel
mogą być stosowane tylko do tego określonego obiektu. - Zasoby w dołączonym
ResourceDictionary
układzie, takim jakStackLayout
lubGrid
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://xamarin.com/schemas/2014/forms"
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>
<!-- Implicit styles -->
<Style TargetType="{x:Type NavigationPage}">
<Setter Property="BarBackgroundColor"
Value="{StaticResource NavigationBarColor}" />
<Setter Property="BarTextColor"
Value="{StaticResource NavigationBarTextColor}" />
</Style>
<Style TargetType="{x:Type 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. Aby uzyskać więcej informacji na temat App
klasy, zobacz Xamarin.Forms App Class (Klasa aplikacji).
Uwaga
Ważne jest również umieszczenie wszystkich zasobów między jawnymi ResourceDictionary
tagami. Jednak ponieważ Xamarin.Forms 3.0 ResourceDictionary
tagi nie są wymagane. ResourceDictionary
Zamiast tego obiekt jest tworzony automatycznie i można wstawić zasoby bezpośrednio między tagami Resources
właściwości-element.
Korzystanie z zasobów w języku XAML
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
.
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 wprowadzenie zmian zasobów środowiska uruchomieniowego w aplikacji. Aby uzyskać więcej informacji na temat rozszerzeń znaczników, zobacz Rozszerzenia znaczników XAML.
Poniższy przykład XAML pokazuje, jak korzystać z zasobów, a także definiuje dodatkowe zasoby w obiekcie StackLayout
:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ResourceDictionaryDemo.HomePage"
Title="Home Page">
<StackLayout Margin="{StaticResource PageMargin}">
<StackLayout.Resources>
<!-- Implicit style -->
<Style TargetType="Button">
<Setter Property="FontSize" Value="Medium" />
<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ższych zrzutach 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 poziomu AppBackgroundColor
kontroli.
Słowniki zasobów autonomicznych
Klasa pochodząca z ResourceDictionary
klasy może również znajdować się w autonomicznym pliku XAML. Następnie można udostępnić plik XAML między aplikacjami.
Aby utworzyć taki plik, dodaj nowy element Widok zawartości lub Strona zawartości do projektu (ale nie widok zawartości lub strona zawartości z tylko plikiem C#). Usuń plik za pomocą kodu, a w pliku XAML zmień nazwę klasy bazowej z ContentView
lub ContentPage
na ResourceDictionary
. Ponadto usuń x:Class
atrybut z tagu głównego pliku.
Poniższy przykład XAML przedstawia ResourceDictionary
nazwę MyResourceDictionary.xaml:
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
<DataTemplate x:Key="PersonDataTemplate">
<ViewCell>
<Grid>
<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.
Domyślnie konsolidator usunie autonomiczne pliki XAML z kompilacji wydania, gdy zachowanie konsolidatora zostanie ustawione w celu połączenia wszystkich zestawów. Aby upewnić się, że autonomiczne pliki XAML pozostają w kompilacji wydania:
Dodaj atrybut niestandardowy
Preserve
do zestawu zawierającego autonomiczne pliki XAML. Aby uzyskać więcej informacji, zobacz Zachowywanie kodu.Ustaw atrybut na
Preserve
poziomie zestawu:[assembly:Preserve(AllMembers = true)]
Aby uzyskać więcej informacji na temat łączenia, zobacz Łączenie aplikacji Xamarin.iOS i Łączenie w systemie Android.
Scalone słowniki zasobów
Scalone słowniki zasobów łączą jeden lub więcej ResourceDictionary
obiektów w inny ResourceDictionary
obiekt .
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ść 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
posiadania akcji kompilacji ustawionej na EmbeddedResource, aby mieć plik za pomocą kodu 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 ResourceDictionary
strony:
<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:LightTheme />
<!-- 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 ResourceDictionary
moż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 zasobów współużytkuje ResourceDictionary
identyczne x:Key
wartości atrybutów, Xamarin.Forms użyj 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 .
Uwaga
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.
Pokrewne łącza
- Rozszerzenia struktury znaczników XAML
- Xamarin.Forms Style
- Łączenie aplikacji platformy Xamarin.iOS
- Łączenie w systemie Android
- ResourceDictionary API
Powiązany film wideo
Więcej filmów na platformie Xamarin można znaleźć w witrynach Channel 9 i YouTube.