Attributo x:Load

Si può usare x:Load per ottimizzare l'avvio, la creazione dell'albero visivo e l'utilizzo della memoria dell'app XAML. L'uso di x:Load ha un effetto visivo simile a Visibility, ad eccezione del fatto che quando l'elemento non viene caricato, la memoria viene rilasciata e internamente viene usato un segnaposto piccolo per contrassegnarne la posizione nella struttura ad albero visuale.

L'elemento dell'interfaccia utente con attributo x:Load può essere caricato e scaricato tramite codice o usando un'espressione x:Bind. Ciò è utile per ridurre i costi degli elementi visualizzati raramente o in modo condizionale. Quando si usa x:Load in un contenitore, ad esempio Grid o StackPanel, il contenitore e tutti i relativi elementi figlio vengono caricati o scaricati come gruppo.

Il rilevamento degli elementi posticipati dal framework XAML aggiunge circa 600 byte all'utilizzo della memoria per ogni elemento attribuito con x:Load, per tenere conto del segnaposto. Pertanto, è possibile usare questo attributo nella misura in cui le prestazioni diminuiscono effettivamente. È consigliabile usarlo solo su elementi che devono essere nascosti. Se si usa x:Load in un contenitore, l'overhead viene pagato solo per l'elemento con l'attributo x:Load.

Importante

L'attributo x:Load è disponibile a partire da Windows 10, versione 1703 (Creators Update). La versione minima di destinazione del progetto Visual Studio deve essere Windows 10 Creators Update (10.0, Build 15063) per poter usare x:Load.

Utilizzo attributo XAML

<object x:Load="True" .../>
<object x:Load="False" .../>
<object x:Load="{x:Bind Path.to.a.boolean, Mode=OneWay}" .../>

Caricare elementi

Sono disponibili diversi modi per caricare gli elementi:

  • Usare un'espressione x:Bind per specificare lo stato di caricamento. L'espressione deve restituire true per caricare e false per scaricare l'elemento.
  • Chiamare FindName con il nome definito nell'elemento.
  • Chiamare GetTemplateChild con il nome definito nell'elemento .
  • In un VisualState, usare un Setter o un'animazione Storyboard destinata all'elemento x:Load.
  • Specificare come destinazione l'elemento scaricato in qualsiasi Storyboard.

NOTA: dopo l'avvio della creazione di un'istanza di un elemento, viene creata nel thread dell'interfaccia utente, in modo da far sì che l'interfaccia utente balbetti se viene creata una quantità eccessiva contemporaneamente.

Dopo la creazione di un elemento posticipato in uno dei modi elencati in precedenza, vengono eseguite diverse operazioni:

  • Viene sollevato l'evento Loaded sull'elemento.
  • Il campo per x:Name è impostato.
  • Tutte le associazioni x:Bind nell'elemento vengono valutate.
  • Se è stata effettuata la registrazione per ricevere notifiche di modifica delle proprietà sulla proprietà contenente gli elementi posticipati, viene generata la notifica.

Scaricamento di elementi

Per scaricare un elemento:

  • Usare un'espressione x:Bind per specificare lo stato di caricamento. L'espressione deve restituire true per caricare e false per scaricare l'elemento.
  • In un controllo Page o UserControl chiamare UnloadObject e passare il riferimento all'oggetto
  • Chiamare Windows.UI.Xaml.Markup.XamlMarkupHelper.UnloadObject e passare il riferimento all'oggetto

Quando un oggetto viene scaricato, verrà sostituito nell'albero con un segnaposto. L'istanza dell'oggetto rimarrà in memoria fino al rilascio di tutti i riferimenti. L'API UnloadObject in un controllo Page/UserControl è progettata per rilasciare i riferimenti contenuti da codegen per x:Name e x:Bind. Se si contengono riferimenti aggiuntivi nel codice dell'app, sarà necessario anche rilasciarli.

Quando un elemento viene scaricato, tutto lo stato associato all'elemento verrà rimosso, quindi se si usa x:Load come versione ottimizzata di Visibility, assicurarsi che tutto lo stato venga applicato tramite associazioni o venga nuovamente applicato dal codice quando viene generato l'evento Loaded.

Restrizioni

Le limitazioni per l'uso di x:Load sono:

  • È necessario definire un valore x:Name per l'elemento, perché è necessario trovare l'elemento in un secondo momento.
  • È possibile usare x:Load solo sui tipi che derivano da UIElement o FlyoutBase.
  • Non è possibile usare x:Load sugli elementi radice in un oggetto Page, un UserControl o un DataTemplate.
  • Non è possibile usare x:Load sugli elementi in un ResourceDictionary.
  • Non è possibile usare x:Load su XAML libero caricato con XamlReader.Load.
  • Lo spostamento di un elemento padre cancella tutti gli elementi che non sono stati caricati.

Osservazioni:

È possibile usare x:Load sugli elementi annidati, ma devono essere realizzati dall'elemento più esterno.  Se si tenta di realizzare un elemento figlio prima che l'elemento padre sia stato realizzato, viene generata un'eccezione.

In genere, è consigliabile rinviare gli elementi che non sono visualizzabili nel primo fotogramma. Una buona linea guida per trovare i candidati da rinviare consiste nel cercare gli elementi creati con Visibilità compressa. Inoltre, l'interfaccia utente attivata dall'interazione dell'utente è un buon posto per cercare gli elementi che è possibile rinviare.

È consigliabile rinviare gli elementi in un controllo ListView, in quanto ridurrà il tempo di avvio, ma potrebbe anche ridurre le prestazioni di panoramica a seconda di ciò che si sta creando. Per migliorare le prestazioni di panoramica, vedere la documentazione relativa all'estensione {x:Bind} markup e alla documentazione dell'attributo x:Phase.

Se l'attributo x:Phase viene usato con x:Load allora, quando viene realizzato un elemento o un albero di elementi, le associazioni vengono applicate fino a e includendo la fase corrente. La fase specificata per x:Phase influisce o controlla lo stato di caricamento dell'elemento. Quando un elemento di elenco viene riciclato come parte della panoramica, gli elementi realizzati si comportano nello stesso modo degli altri elementi attivi e le associazioni compilate (associazioni {x:Bind}) vengono elaborate usando le stesse regole, inclusa la suddivisione in fasi.

Una linea guida generale consiste nel misurare le prestazioni dell'app prima e dopo per assicurarsi di ottenere le prestazioni desiderate.

Esempio

<StackPanel>
    <Grid x:Name="DeferredGrid" x:Load="False">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>

        <Rectangle Height="100" Width="100" Fill="Orange" Margin="0,0,4,4"/>
        <Rectangle Height="100" Width="100" Fill="Green" Grid.Column="1" Margin="4,0,0,4"/>
        <Rectangle Height="100" Width="100" Fill="Blue" Grid.Row="1" Margin="0,4,4,0"/>
        <Rectangle Height="100" Width="100" Fill="Gold" Grid.Row="1" Grid.Column="1" Margin="4,4,0,0"
                   x:Name="one" x:Load="{x:Bind (x:Boolean)CheckBox1.IsChecked, Mode=OneWay}"/>
        <Rectangle Height="100" Width="100" Fill="Silver" Grid.Row="1" Grid.Column="1" Margin="4,4,0,0"
                   x:Name="two" x:Load="{x:Bind Not(CheckBox1.IsChecked), Mode=OneWay}"/>
    </Grid>

    <Button Content="Load elements" Click="LoadElements_Click"/>
    <Button Content="Unload elements" Click="UnloadElements_Click"/>
    <CheckBox x:Name="CheckBox1" Content="Swap Elements" />
</StackPanel>
// This is used by the bindings between the rectangles and check box.
private bool Not(bool? value) { return !(value==true); }

private void LoadElements_Click(object sender, RoutedEventArgs e)
{
    // This will load the deferred grid, but not the nested
    // rectangles that have x:Load attributes.
    this.FindName("DeferredGrid"); 
}

private void UnloadElements_Click(object sender, RoutedEventArgs e)
{
     // This will unload the grid and all its child elements.
     this.UnloadObject(DeferredGrid);
}