Udostępnij za pośrednictwem


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 Applicationklasy , ale często korzysta z wielu klas, które pochodzą z VisualElementklasy , 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 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://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 ResourceDictionaryStaticResource 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:

Korzystanie z zasobówWłaściwych zasobach

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:

  1. Dodaj atrybut niestandardowy Preserve do zestawu zawierającego autonomiczne pliki XAML. Aby uzyskać więcej informacji, zobacz Zachowywanie kodu.

  2. 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 ResourceDictionaryobiekt .

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 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: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 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 zasobów współużytkuje ResourceDictionary identyczne x:Key wartości atrybutów, Xamarin.Forms użyj 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 .

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.

Więcej filmów na platformie Xamarin można znaleźć w witrynach Channel 9 i YouTube.