Dizionari risorse
Un'interfaccia utente dell'app multipiattaforma .NET (.NET MAUI) ResourceDictionary è un repository per le risorse usate da un'app MAUI .NET. Le risorse tipiche archiviate in un ResourceDictionary oggetto includono stili, modelli di controllo, modelli di dati, convertitori e colori.
È possibile fare riferimento alle risorse XAML archiviate in un ResourceDictionary oggetto e applicarle agli elementi usando l'estensione StaticResource
di markup o DynamicResource
. In C# le risorse possono anche essere definite in un ResourceDictionary oggetto e quindi a cui si fa riferimento e applicate agli elementi usando un indicizzatore basato su stringa.
Suggerimento
In Visual Studio un file basato su ResourceDictionary XAML supportato da un file code-behind può essere aggiunto al progetto dal modello di elemento ResourceDictionary (XAML) di .NET MAUI.
Creare le risorse
Ogni VisualElement oggetto derivato ha una Resources
proprietà , ovvero un oggetto ResourceDictionary che può contenere risorse. Analogamente, un Application
oggetto derivato ha una Resources
proprietà , ovvero un ResourceDictionary oggetto che può contenere risorse.
Un'app .NET MAUI può contenere solo una singola classe che deriva da Application
, ma spesso usa molte classi che derivano da VisualElement, incluse pagine, layout e visualizzazioni. Uno di questi oggetti può avere la relativa Resources
proprietà impostata su un ResourceDictionary oggetto contenente le risorse. Scelta della posizione in cui inserire un impatto particolare ResourceDictionary in cui è possibile usare le risorse:
- Le risorse in un ResourceDictionary oggetto collegato a una vista, ad esempio Button o Label, possono essere applicate solo a tale oggetto specifico.
- Le risorse in un ResourceDictionary layout collegato a un layout, ad esempio StackLayout o Grid, possono essere applicate al layout e a tutti gli elementi figlio di tale layout.
- Le risorse in un ResourceDictionary oggetto definito a livello di pagina possono essere applicate alla pagina e a tutti i relativi elementi figlio.
- Le risorse in un ResourceDictionary definito a livello di applicazione possono essere applicate in tutta l'app.
Ad eccezione degli stili impliciti, ogni risorsa nel dizionario risorse deve avere una chiave stringa univoca definita con l'attributo x:Key
.
Il codice XAML seguente mostra le risorse definite in un livello ResourceDictionary di applicazione nel file 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>
In questo esempio il dizionario risorse definisce una Thickness
risorsa, più Color risorse e due risorse implicite Style .
Importante
L'inserimento di risorse direttamente tra i tag dell'elemento Resources
proprietà crea automaticamente un ResourceDictionary oggetto . Tuttavia, è anche valido inserire tutte le risorse tra tag facoltativi ResourceDictionary .
Utilizzare le risorse
Ogni risorsa ha una chiave specificata usando l'attributo x:Key
, che diventa la chiave del dizionario in ResourceDictionary. La chiave viene usata per fare riferimento a una risorsa da con l'estensione ResourceDictionary StaticResource
di markup XAML o DynamicResource
.
L'estensione StaticResource
di markup è simile all'estensione DynamicResource
di markup in quanto entrambi usano una chiave del dizionario per fare riferimento a un valore da un dizionario risorse. Tuttavia, mentre l'estensione StaticResource
di markup esegue una ricerca in un singolo dizionario, l'estensione DynamicResource
di markup mantiene un collegamento alla chiave del dizionario. Pertanto, se la voce del dizionario associata alla chiave viene sostituita, la modifica viene applicata all'elemento visivo. In questo modo è possibile apportare modifiche alle risorse di runtime in un'app. Per altre informazioni sulle estensioni di markup, vedi Estensioni di markup XAML.
L'esempio XAML seguente mostra come usare le risorse e definire anche una risorsa aggiuntiva in un StackLayoutoggetto :
<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>
In questo esempio, l'oggetto ContentPage utilizza lo stile implicito definito nel dizionario risorse a livello di applicazione. L'oggetto StackLayout utilizza la PageMargin
risorsa definita nel dizionario risorse a livello di applicazione, mentre l'oggetto Button utilizza lo stile implicito definito nel StackLayout dizionario risorse. Ciò comporta l'aspetto illustrato nello screenshot seguente:
Importante
Le risorse specifiche di una singola pagina non devono essere incluse in un dizionario risorse a livello di applicazione, in quanto tali risorse verranno quindi analizzate all'avvio dell'app anziché quando richiesto da una pagina. Per altre informazioni, vedere Ridurre le dimensioni del dizionario risorse dell'applicazione.
Comportamento di ricerca delle risorse
Il processo di ricerca seguente si verifica quando viene fatto riferimento a una risorsa con l'estensione StaticResource
di markup o DynamicResource
:
- La chiave richiesta viene verificata nel dizionario risorse, se esistente, per l'elemento che imposta la proprietà. Se viene trovata la chiave richiesta, viene restituito il relativo valore e il processo di ricerca termina.
- Se non viene trovata una corrispondenza, il processo di ricerca cerca la struttura ad albero visuale verso l'alto, controllando il dizionario risorse di ogni elemento padre. Se viene trovata la chiave richiesta, viene restituito il relativo valore e il processo di ricerca termina. In caso contrario, il processo continua verso l'alto fino a quando non viene raggiunto l'elemento radice.
- Se non viene trovata una corrispondenza nell'elemento radice, viene esaminato il dizionario risorse a livello di applicazione.
- Se non viene ancora trovata una corrispondenza, viene generata un'eccezione
XamlParseException
.
Pertanto, quando il parser XAML rileva un'estensione StaticResource
di markup o DynamicResource
, cerca una chiave corrispondente passando attraverso la struttura ad albero visuale, usando la prima corrispondenza trovata. Se la ricerca termina nella pagina e la chiave non è ancora stata trovata, il parser XAML cerca nell'oggetto ResourceDictionary App
associato. Se la chiave non viene ancora trovata, viene generata un'eccezione.
Eseguire l'override delle risorse
Quando le risorse condividono le chiavi, le risorse definite più in basso nella struttura ad albero visuale avranno la precedenza su quelle definite più in alto. Ad esempio, l'impostazione di una AppBackgroundColor
risorsa su AliceBlue
a livello di applicazione verrà sostituita da una risorsa a livello AppBackgroundColor
di pagina impostata su Teal
. Analogamente, una risorsa a livello di pagina verrà sostituita da una risorsa a livello AppBackgroundColor
AppBackgroundColor
di layout o di visualizzazione.
Dizionari risorse autonomi
Un ResourceDictionary oggetto può anche essere creato come file XAML autonomo che non è supportato da un file code-behind. Per creare un oggetto autonomo ResourceDictionary, aggiungere un nuovo ResourceDictionary file al progetto con il modello di elemento ResourceDictionary (XAML) di .NET MAUI ed eliminare il relativo file code-behind. Quindi, nel file XAML rimuovere l'attributo x:Class
dal ResourceDictionary tag vicino all'inizio del file. Aggiungere anche <?xaml-comp compile="true" ?>
dopo l'intestazione XML per assicurarsi che il codice XAML venga compilato.
Un ResourceDictionary oggetto può anche essere creato come file XAML autonomo che non è supportato da un file code-behind. Per creare un oggetto autonomo ResourceDictionary, aggiungere un nuovo ResourceDictionary file al progetto con il modello di elemento ResourceDictionary (XAML) di .NET MAUI ed eliminare il relativo file code-behind. Quindi, nel file XAML rimuovere l'attributo x:Class
dal ResourceDictionary tag vicino all'inizio del file. Per impostazione predefinita, un codice XAML autonomo ResourceDictionary è compilato, a meno che non <?xaml-comp compile="false" ?>
venga specificato dopo l'intestazione XML.
Nota
Un'azione di compilazione autonoma ResourceDictionary deve avere un'azione di compilazione di MauiXaml.
L'esempio XAML seguente mostra un oggetto autonomo ResourceDictionary denominato 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>
In questo esempio l'oggetto ResourceDictionary contiene una singola risorsa, ovvero un oggetto di tipo DataTemplate. MyResourceDictionary.xaml può essere utilizzato unendolo in un altro dizionario risorse.
Unisci dizionari risorse
I dizionari risorse possono essere combinati unendo uno o più ResourceDictionary oggetti in un altro ResourceDictionaryoggetto .
Unire dizionari risorse locali
Un file locale ResourceDictionary può essere unito a un altro ResourceDictionary creando un ResourceDictionary oggetto la cui Source
proprietà è impostata sul nome file del file XAML con le risorse:
<ContentPage ...>
<ContentPage.Resources>
<!-- Add more resources here -->
<ResourceDictionary Source="MyResourceDictionary.xaml" />
<!-- Add more resources here -->
</ContentPage.Resources>
...
</ContentPage>
Questa sintassi non crea un'istanza della MyResourceDictionary
classe . Fa invece riferimento al file XAML. Per questo motivo, quando si imposta la Source
proprietà , non è necessario un file code-behind e l'attributo x:Class
può essere rimosso dal tag radice del file MyResourceDictionary.xaml .
Importante
La ResourceDictionary.Source
proprietà può essere impostata solo da XAML.
Unire dizionari risorse da altri assembly
Un ResourceDictionary oggetto può anche essere unito in un altro ResourceDictionary aggiungendolo nella MergedDictionaries
proprietà di ResourceDictionary. Questa tecnica consente di unire i dizionari delle risorse, indipendentemente dall'assembly in cui risiedono. L'unione di dizionari risorse da assembly esterni richiede l'impostazione ResourceDictionary di un'azione di compilazione su MauiXaml, per avere un file code-behind e per definire l'attributo x:Class
nel tag radice del file.
Avviso
Anche la classe ResourceDictionary definisce una proprietà MergedWith
. Tuttavia, questa proprietà è stata deprecata e non deve più essere utilizzata.
L'esempio di codice seguente mostra due dizionari di risorse aggiunti alla MergedDictionaries
raccolta di un livello ResourceDictionarydi pagina:
<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>
In questo esempio, un dizionario risorse dello stesso assembly e un dizionario risorse di un assembly esterno vengono uniti nel dizionario risorse a livello di pagina. Inoltre, è anche possibile aggiungere altri ResourceDictionary oggetti all'interno dei MergedDictionaries
tag property-element e altre risorse all'esterno di tali tag.
Importante
In un ResourceDictionaryoggetto può essere presente un MergedDictionaries
solo tag di elemento proprietà, ma è possibile inserire tutti gli ResourceDictionary oggetti in tale elemento come richiesto.
Quando le risorse unite ResourceDictionary condividono valori di attributo identici x:Key
, .NET MAUI usa la precedenza delle risorse seguente:
- Risorse locali del dizionario risorse.
- Le risorse contenute nei dizionari risorse unite tramite la
MergedDictionaries
raccolta, nell'ordine inverso in cui sono elencate nellaMergedDictionaries
proprietà .
Suggerimento
La ricerca di dizionari risorse può essere un'attività a elevato utilizzo di calcolo se un'app contiene più dizionari di risorse di grandi dimensioni. Pertanto, per evitare ricerche non necessarie, è necessario assicurarsi che ogni pagina in un'applicazione usi solo dizionari risorse appropriati per la pagina.
Usare un dizionario risorse basato su XAML dal codice
I dizionari di risorse definiti in XAML possono essere utilizzati nel codice, a condizione che sia ResourceDictionary supportato da un file code-behind. In Visual Studio i file basati su ResourceDictionary XAML supportati da file code-behind possono essere aggiunti al progetto dal modello di elemento ResourceDictionary (XAML) di .NET MAUI:
I dizionari di risorse basati su XAML supportati da file code-behind possono quindi essere usati da C# aggiungendoli alla MergedDictionaries raccolta del dizionario risorse:
Resources.MergedDictionaries.Add(new MyMauiApp.Resources.Styles.MyColors());
Resources.MergedDictionaries.Add(new MyMauiApp.Resources.Styles.MyStyles());
Accedere alle risorse in base alla chiave dal codice
È possibile accedere alle risorse in un dizionario risorse dal codice come qualsiasi altro dizionario.
L'esempio seguente illustra come recuperare e applicare una risorsa dal dizionario risorse di una pagina:
// 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;
}
Questo è l'approccio consigliato che garantisce che .NET MAUI non generi un'eccezione KeyNotFoundException
se non è in grado di recuperare una risorsa dal codice. Ciò può verificarsi quando un dizionario risorse unito è costituito da risorse definite in un file XAML e risorse inline. Per altre informazioni, vedere Problema di GitHub n. 11214.
Nota
Per recuperare le risorse a livello di app dal codice, accedere al App.Current.Resources
dizionario risorse.