Compartir a través de


Atributo x:Load

Puedes usar x:Load para optimizar el inicio, la creación de árboles visuales y el uso de memoria de la aplicación XAML. El uso de x:Load tiene un efecto visual similar a Visibility, salvo que cuando el elemento no está cargado, su memoria se libera y se usa internamente un pequeño marcador de posición para marcar su lugar en el árbol visual.

El elemento de la interfaz de usuario al que se le ha atribuido x:Load se puede cargar y descargar dinámicamente mediante código o mediante una expresión x:Bind. Esto resulta útil para reducir los costos de los elementos que se muestran con poca frecuencia o condicionalmente. Cuando se usa x:Load en un contenedor como Grid o StackPanel, el contenedor y todos sus elementos secundarios se cargan o descargan como un grupo.

El seguimiento de elementos aplazados por la estructura XAML agrega aproximadamente 600 bytes al uso de memoria de cada elemento atribuido con x:Load, para tener en cuenta el marcador de posición. Por lo tanto, es posible sobreutilizar este atributo en la medida en que el rendimiento disminuya realmente. Se recomienda que solo lo use en elementos que deba ocultar. Si usa x:Load en un contenedor, la sobrecarga solo se paga por el elemento con el atributo x:Load.

Importante

El atributo x:Load está disponible a partir de Windows 10, versión 1703 (Creators Update). La versión mínima dirigida por el proyecto de Visual Studio debe ser Windows 10 Creators Update (10.0, compilación 15063) para usar x:Load.

Uso de atributos XAML

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

Elementos de carga

Hay varias maneras diferentes de cargar los elementos:

  • Use una expresión x:Bind para especificar el estado de carga. La expresión debe devolver true para cargar y false para descargar el elemento.
  • Llame a FindName con el nombre que definió del elemento.
  • Utilice GetTemplateChild con el nombre que has definido en el elemento.
  • En visualState, use una animación Setter o Storyboard que tenga como destino el elemento x:Load.
  • Dirija el elemento descargado en cualquier guión gráfico.

Nota:

Una vez que se inicia la instanciación de un elemento, se crea en el hilo de la interfaz de usuario, por lo que podría provocar que la interfaz de usuario se congele si se crea demasiado a la vez.

Una vez creado un elemento diferido en cualquiera de las formas enumeradas anteriormente, suceden varias cosas:

  • Se genera el evento Loaded en el elemento.
  • Se establece el campo para x:Name.
  • Se aplican las vinculaciones x:Bind en el elemento.
  • Si se ha registrado para recibir notificaciones de cambios en la propiedad que incluye los elementos diferidos, se genera una notificación.

Descargar elementos

Para descargar un elemento:

  • Use una expresión x:Bind para especificar el estado de carga. La expresión debe devolver true para cargar y false para descargar el elemento.
  • En una página o UserControl, llame a UnloadObject y pase la referencia de objeto.
  • Llame a Microsoft.UI.Xaml.Markup.XamlMarkupHelper.UnloadObject y pase la referencia de objeto.

Cuando se descarga un objeto, se reemplazará en el árbol por un marcador de posición. La instancia de objeto permanecerá en memoria hasta que se hayan liberado todas las referencias. La API UnloadObject en page/UserControl está diseñada para liberar las referencias que contiene codegen para x:Name y x:Bind. Si mantiene referencias adicionales en el código de la aplicación, estas también deberán liberarse.

Cuando se descarga un elemento, se descartará todo el estado asociado al elemento, por lo que si usa x:Load como una versión optimizada de Visibility, asegúrese de que todo el estado se aplica a través de enlaces o se vuelve a aplicar mediante código cuando se desencadena el evento Loaded.

Restrictions

Las restricciones para usar x:Load son:

  • Debe definir un x:Name para el elemento, ya que debe haber una manera de encontrar el elemento más adelante.
  • Solo puede usar x:Load en tipos que derivan de UIElement o FlyoutBase.
  • No se puede usar x:Load en elementos raíz de un elemento Page, un UserControl o dataTemplate.
  • No se puede usar x:Load en elementos de resourceDictionary.
  • No puedes usar x:Load en XAML flexible cargado con XamlReader.Load.
  • Al mover un elemento primario se borrarán todos los elementos que no se hayan cargado.

Observaciones

Puede usar x:Load en elementos anidados, pero deben realizarse desde el elemento más externo hacia dentro.  Si intenta instanciar un elemento secundario antes de que se haya instanciado el elemento padre, se genera una excepción.

Normalmente, se recomienda aplazar los elementos que no se pueden ver en el primer marco. Una buena guía para buscar candidatos a aplazar es buscar elementos que se crean con visibilidad colapsada. Además, la interfaz de usuario desencadenada por la interacción del usuario es un buen lugar para buscar elementos que se pueden aplazar.

Tenga cuidado con aplazar los elementos en un control ListView, ya que aumentará el tiempo de inicio, pero también podría reducir el rendimiento del movimiento panorámico en función de lo que esté creando. Si desea aumentar el rendimiento del movimiento panorámico, consulte la documentación sobre la extensión de marcado {x:Bind} y el atributo x:Phase .

Si el atributo x:Phase se usa junto con x:Load, entonces, cuando se realiza un elemento o un árbol de elementos, los enlaces se aplican hasta e incluyendo la fase actual. La fase especificada para x:Phase afecta o controla el estado de carga del elemento. Cuando se recicla un elemento de lista como parte del movimiento panorámico, los elementos realizados se comportarán de la misma manera que otros elementos activos y los enlaces compilados ({x:Bind} ) se procesan con las mismas reglas, incluida la fase.

Una guía general es medir el rendimiento de la aplicación antes y después para asegurarse de obtener el rendimiento que desee.

Para minimizar los cambios en el comportamiento (aparte del rendimiento) al agregar x:Load a un elemento, los enlaces x:Bind se calculan en sus momentos normales, como si no hubiera elementos usados x:Load. Por ejemplo, los enlaces OneTime x:Bind se calculan cuando se carga el elemento raíz. Si el elemento no se realiza en el momento en que se calcula el enlace x:Bind , el valor calculado se guarda y se aplica al elemento cuando se carga. Este comportamiento puede ser sorprendente si esperaba que los enlaces x:Bind se calculen cuando el elemento se materializa.

Example

<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);
}