Condividi tramite


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:

Utilizzo delle risorse del dizionario risorse.

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:

  1. Risorse locali del dizionario risorse.
  2. Le risorse contenute nei dizionari risorse unite tramite la MergedDictionaries raccolta, nell'ordine inverso in cui sono elencate nella MergedDictionaries 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:

Screenshot dei dizionari risorse supportati dal code-behind.

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.