Xamarin.Forms dictionnaires de ressources
Il ResourceDictionary
s’agit d’un référentiel pour les ressources utilisées par une Xamarin.Forms application. Les ressources classiques stockées dans un ResourceDictionary
style incluent des styles, des modèles de contrôle, des modèles de données, des couleurs et des convertisseurs.
En XAML, les ressources stockées dans un ResourceDictionary
objet peuvent être référencées et appliquées aux éléments à l’aide de l’extension ou DynamicResource
du StaticResource
balisage. En C#, les ressources peuvent également être définies dans un ResourceDictionary
, puis référencées et appliquées à des éléments, à l’aide d’un indexeur basé sur des chaînes. Toutefois, il est peu avantageux d’utiliser un ResourceDictionary
objet en C#, car les objets partagés peuvent être stockés en tant que champs ou propriétés, et accessibles directement sans avoir à les récupérer d’abord à partir d’un dictionnaire.
Créer des ressources en XAML
Chaque objet dérivé VisualElement
a une propriété Resources
, qui est un ResourceDictionary
pouvant contenir des ressources. De même, un objet dérivé Application
a une propriété Resources
, qui est un ResourceDictionary
pouvant contenir des ressources.
Une Xamarin.Forms application contient uniquement une classe qui dérive de Application
, mais utilise souvent de nombreuses classes qui dérivent VisualElement
, y compris les pages, les mises en page et les contrôles. L’un de ces objets peut avoir sa propriété Resources
définie sur un ResourceDictionary
contenant des ressources. Choisir l’emplacement d’un ResourceDictionary
a un impact sur l’usage des ressources :
- Les ressources d’un
ResourceDictionary
élément attaché à une vue telle queButton
ouLabel
ne peuvent être appliquées qu’à cet objet particulier. - Les ressources d’une
ResourceDictionary
disposition jointe, telles queStackLayout
ouGrid
peuvent être appliquées à la disposition et à tous les enfants de cette disposition. - Les ressources d’un
ResourceDictionary
défini au niveau de la page peuvent être appliquées à la page et à tous ses enfants. - Les ressources d’une
ResourceDictionary
application définie au niveau de l’application peuvent être appliquées dans l’ensemble de l’application.
À l’exception des styles implicites, chaque ressource du dictionnaire de ressources doit avoir une clé de chaîne unique définie avec l’attribut x:Key
.
Le code XAML suivant montre les ressources d’un ResourceDictionary
défini au niveau de l’application dans le fichier 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>
Dans cet exemple, le dictionnaire de ressources définit une Thickness
ressource, plusieurs Color
ressources et deux ressources implicites Style
. Pour plus d’informations sur la classe, consultez Xamarin.Forms Classe d’applicationApp
.
Remarque
Il est également valide pour placer toutes les ressources entre des balises explicites ResourceDictionary
. Toutefois, étant donné que Xamarin.Forms la version 3.0 des ResourceDictionary
balises n’est pas requise. Au lieu de cela, l’objet ResourceDictionary
est créé automatiquement et vous pouvez insérer les ressources directement entre les Resources
balises d’élément de propriété.
Consommer des ressources en XAML
Chaque ressource a une clé spécifiée à l’aide de l’attribut x:Key
, qui devient sa clé de dictionnaire dans le ResourceDictionary
. La clé est utilisée pour référencer une ressource à partir de l’extension ResourceDictionary
de balisage ou DynamicResource
de l’extension StaticResource
de balisage.
L’extension de balisage StaticResource
est similaire à l’extension DynamicResource
en ce que toutes les deux utilisent une clé de dictionnaire pour extraire une valeur d’un dictionnaire de ressources. Toutefois, alors que l’extension de balisage StaticResource
effectue une seule recherche dans le dictionnaire, l’extension DynamicResource
conserve un lien vers la clé de dictionnaire. Par conséquent, si l’entrée de dictionnaire associée à la clé est remplacée, la modification est appliquée à l’élément visuel. Cela permet d’apporter des modifications aux ressources runtime dans une application. Pour plus d’informations sur les extensions de balisage, consultez Extensions de balisage XAML.
L’exemple XAML suivant montre comment consommer des ressources et définit également des ressources supplémentaires dans un 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>
Dans cet exemple, l’objet ContentPage
consomme le style implicite défini dans le dictionnaire de ressources au niveau de l’application. L’objet StackLayout
consomme la ressource PageMargin
définie dans le dictionnaire de ressources au niveau de l’application, tandis que l’objet Button
consomme le style implicite défini dans le dictionnaire de ressources StackLayout
. Cela donne l’affichage illustré dans les captures d’écran suivantes :
Important
Les ressources spécifiques à une seule page ne doivent pas être incluses dans un dictionnaire de ressources au niveau de l’application, car ces ressources seront ensuite analysées au démarrage de l’application au lieu d’être requises par une page. Pour plus d’informations, consultez Réduire la taille du dictionnaire de ressources d’application.
Comportement de la recherche de ressources
Le processus de recherche suivant se produit lorsqu’une ressource est référencée avec l’extension de balisage StaticResource
ou DynamicResource
:
- La clé demandée est recherchée dans le dictionnaire de ressources, s’il existe, pour l’élément qui définit la propriété. Si la clé demandée est trouvée, sa valeur est retournée et le processus de recherche se termine.
- Si aucune correspondance n’est trouvée, le processus de recherche explore l’arborescence d’éléments visuels vers le haut, en vérifiant le dictionnaire de ressources de chaque élément parent. Si la clé demandée est trouvée, sa valeur est retournée et le processus de recherche se termine. Sinon, le processus continue vers le haut jusqu’à ce que l’élément racine soit atteint.
- Si aucune correspondance n’est trouvée au niveau de l’élément racine, le dictionnaire de ressources au niveau de l’application est examiné.
- Si aucune correspondance n’est trouvée, une exception
XamlParseException
est retournée.
Par conséquent, lorsque l’analyseur XAML rencontre une extension de balisage StaticResource
ou DynamicResource
, il recherche une clé correspondante en parcourant l’arborescence d’éléments visuels jusqu’à trouver une correspondance. Si cette recherche atteint la page et que la clé n’a toujours pas été trouvée, l’analyseur XAML recherche le ResourceDictionary
attaché à l’objet App
. Si la clé est toujours introuvable, une exception est levée.
Remplacer des ressources
Lorsque des ressources ont la même clé, les ressources définies plus bas dans l’arborescence visuelle sont prioritaires sur celles définies plus haut. Par exemple, une ressource AppBackgroundColor
définie sur AliceBlue
au niveau de l’application sera remplacée par une ressource AppBackgroundColor
définie sur Teal
au niveau de la page. De même, une ressource au niveau AppBackgroundColor
de la page sera remplacée par une ressource au niveau AppBackgroundColor
du contrôle.
Dictionnaires de ressources autonomes
Une classe dérivée de ResourceDictionary
peut également se trouver dans un fichier XAML autonome. Le fichier XAML peut ensuite être partagé entre les applications.
Pour créer un tel fichier, ajoutez un nouvel élément d’affichage de contenu ou de page de contenu au projet (mais pas une vue de contenu ou une page de contenu avec uniquement un fichier C#). Supprimez le fichier code-behind et, dans le fichier XAML, modifiez le nom de la classe de base de ContentView
ou ContentPage
vers ResourceDictionary
. En outre, supprimez l’attribut x:Class
de la balise racine du fichier.
L’exemple XAML suivant montre un ResourceDictionary
nom 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>
Dans cet exemple, le ResourceDictionary
contient une seule ressource, qui est un objet de type DataTemplate
. MyResourceDictionary.xaml peut être consommé en le fusionnant avec un autre dictionnaire de ressources.
Par défaut, l’éditeur de liens supprime les fichiers XAML autonomes des builds de mise en production lorsque le comportement de l’éditeur de liens est défini pour lier tous les assemblys. Pour vous assurer que les fichiers XAML autonomes restent dans une build de mise en production :
Ajoutez un attribut personnalisé
Preserve
à l’assembly contenant les fichiers XAML autonomes. Pour plus d’informations, consultez Conservation du code.Définissez l’attribut au niveau de l’assembly
Preserve
:[assembly:Preserve(AllMembers = true)]
Pour plus d’informations sur la liaison, consultez Liaison d’applications Xamarin.iOS et Liaison sur Android.
Dictionnaires de ressources fusionnés
Les dictionnaires de ressources fusionnés combinent un ou plusieurs ResourceDictionary
objets dans un autre ResourceDictionary
.
Fusionner des dictionnaires de ressources locales
Un fichier ResourceDictionary
local peut être fusionné à un autre ResourceDictionary
en créant un objet ResourceDictionary
dont la propriété Source
est définie sur le nom de fichier XAML avec les ressources suivantes :
<ContentPage ...>
<ContentPage.Resources>
<!-- Add more resources here -->
<ResourceDictionary Source="MyResourceDictionary.xaml" />
<!-- Add more resources here -->
</ContentPage.Resources>
...
</ContentPage>
Cette syntaxe n’instancie pas la classe MyResourceDictionary
. À la place, elle fait référence au fichier XAML. Pour cette raison, lorsque vous définissez la propriété Source
, un fichier code-behind n’est pas obligatoire et l’attribut x:Class
peut être supprimé de la balise racine du fichier MyResourceDictionary.xaml.
Important
La propriété Source
ne peut être définie qu’à partir de XAML.
Fusionner des dictionnaires de ressources à partir d’autres assemblys
Un ResourceDictionary
peut également être fusionné à un autre ResourceDictionary
en l’ajoutant à la propriété MergedDictionaries
du ResourceDictionary
. Cette technique permet de fusionner des dictionnaires de ressources, quel que soit l’assembly dans lequel ils se trouvent. La fusion de dictionnaires de ressources à partir d’assemblys externes nécessite qu’une ResourceDictionary
action de génération soit définie sur EmbeddedResource, qu’elle ait un fichier code-behind et qu’elle définisse l’attribut x:Class
dans la balise racine du fichier.
Avertissement
La classe ResourceDictionary
définit aussi une propriété MergedWith
. Toutefois, cette propriété est déconseillée et ne doit plus être utilisée.
L’exemple de code suivant montre deux dictionnaires de ressources ajoutés à la collection MergedDictionaries
d’un ResourceDictionary
défini au niveau de la page :
<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>
Dans cet exemple, un dictionnaire de ressources provenant du même assembly et un dictionnaire de ressources provenant d’un assembly externe sont fusionnés avec le dictionnaire de ressources défini au niveau de la page. En outre, vous pouvez ajouter d’autres objets ResourceDictionary
dans les balises d’élément de propriété MergedDictionaries
et d’autres ressources en dehors de ces balises.
Important
Il ne peut y avoir qu’une seule balise d’élément de propriété MergedDictionaries
dans un ResourceDictionary
, mais vous pouvez y placer autant d’objets ResourceDictionary
que nécessaire.
Lorsque les ressources fusionnées ResourceDictionary
partagent des valeurs d’attribut identiques x:Key
, Xamarin.Forms utilise la priorité des ressources suivante :
- Ressources liées localement au dictionnaire de ressources.
- Ressources contenues dans les dictionnaires de ressources qui ont été fusionnés via la collection
MergedDictionaries
, dans l’ordre inverse de leur listage dans la propriétéMergedDictionaries
.
Remarque
La recherche de dictionnaires de ressources peut être une tâche gourmande en calcul si une application contient plusieurs dictionnaires de ressources volumineux. Par conséquent, pour éviter des recherches inutiles, assurez-vous que chaque page d’une application utilise uniquement des dictionnaires de ressources appropriés.
Liens connexes
- Extensions de balisage XAML
- Xamarin.Forms Styles
- Liaison d’applications Xamarin.iOS
- Liaison sur Android
- ResourceDictionary API