> For the complete documentation index, see [llms.txt](https://elguerre.gitbook.io/de0an/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://elguerre.gitbook.io/de0an/capitulo-9-la-construccion.-navegacion-y-configuracion-de-usuario/rapidez-y-mejora-de-rendimiento.md).

# Rapidez y Mejora de Rendimiento

En esta sección, abordaremos diversas técnicas y estrategias para optimizar el rendimiento de nuestra aplicación, asegurando una experiencia de usuario fluida y eficiente. Nos centraremos en aspectos como la paginación de servicios, la carga incremental de datos, el cacheado de imágenes, y la optimización de controles como `GridView`. Además, exploraremos herramientas y métodos para mejorar el repintado de la interfaz y gestionar recursos de manera eficiente.

## Paginación de Servicios

La paginación es una técnica esencial para manejar grandes conjuntos de datos sin sobrecargar la aplicación ni el servidor. Consiste en dividir los datos en páginas más pequeñas que se cargan según sea necesario, mejorando así el rendimiento y la responsividad.

**Implementación de Paginación:**

1. **Solicitud de Datos por Páginas:**

   Al realizar una solicitud al servicio, se especifica el número de página y el tamaño de la página (cantidad de elementos por página).

   ```csharp
   public async Task<PaginatedResult<Project>> GetProjectsAsync(int pageNumber, int pageSize)
   {
       // Lógica para realizar la solicitud al servicio con paginación
   }
   ```
2. **Manejo de la Respuesta Paginada:**

   La respuesta del servicio debe incluir información sobre la página actual, el total de páginas, y los elementos de la página.

   ```csharp
   public class PaginatedResult<T>
   {
       public int CurrentPage { get; set; }
       public int TotalPages { get; set; }
       public IEnumerable<T> Items { get; set; }
   }
   ```
3. **Integración con la Interfaz de Usuario:**

   Utilizar controles como `ListView` o `GridView` para mostrar los datos paginados y manejar la navegación entre páginas.

## Carga Incremental (Incremental Loading)

La carga incremental, también conocida como "lazy loading", es una técnica que mejora el rendimiento al cargar solo la información necesaria en el momento preciso, reduciendo así los tiempos de carga inicial y optimizando el uso de recursos.

**Implementación de Carga Incremental:**

1. **Configuración de Propiedades:**

   * `IncrementalLoadingTrigger="Edge"`: Define el punto en el que se dispara la carga de más datos, generalmente cuando el usuario se acerca al final de la lista.
   * `IncrementalLoadingThreshold`: Establece un umbral que determina cuán cerca del final debe estar el usuario antes de cargar más datos. Un valor de cero solo cargará la primera página.
   * `DataFetchSize`: Define la cantidad de elementos a cargar en cada solicitud.

   ```xml
   <ListView
       ItemsSource="{Binding Projects}"
       IncrementalLoadingTrigger="Edge"
       IncrementalLoadingThreshold="100"
       IsItemClickEnabled="True">
       <!-- Template -->
   </ListView>
   ```
2. **Implementación del Mecanismo de Carga:**

   Implementar una interfaz como `ISupportIncrementalLoading` en el ViewModel para manejar la carga de datos de manera asíncrona.

   ```csharp
   public class ProjectCollection : ObservableCollection<Project>, ISupportIncrementalLoading
   {
       private bool _hasMoreItems = true;
       private int _currentPage = 0;
       private readonly int _pageSize = 20;
       private readonly IDataService _dataService;

       public ProjectCollection(IDataService dataService)
       {
           _dataService = dataService;
       }

       public bool HasMoreItems => _hasMoreItems;

       public async Task<LoadMoreItemsResult> LoadMoreItemsAsync(uint count)
       {
           var result = await _dataService.GetProjectsAsync(_currentPage, _pageSize);
           foreach(var project in result.Items)
           {
               this.Add(project);
           }
           _currentPage++;
           _hasMoreItems = _currentPage < result.TotalPages;
           return new LoadMoreItemsResult { Count = (uint)result.Items.Count() };
       }
   }
   ```

## Mejora en el Repintado tras la Carga de Datos

Optimizar el repintado de la interfaz de usuario tras la carga de datos es crucial para mantener una experiencia de usuario fluida. Podemos lograr esto mediante el uso de fases declarativas o programáticas.

**Técnicas de Mejora:**

* **Fases Declarativas:**

  Utilizar propiedades como `ShowsScrollingPlaceholders="True"` para indicar al `ListView` o `GridView` que muestre marcadores de posición mientras se cargan los datos.

  ```xml
  <ListView
      ItemsSource="{Binding Projects}"
      IncrementalLoadingTrigger="Edge"
      IncrementalLoadingThreshold="100"
      IsItemClickEnabled="True"
      ShowsScrollingPlaceholders="True">
      <!-- Template -->
  </ListView>
  ```
* **Fases Programáticas:**

  Controlar manualmente el repintado de la interfaz mediante código para optimizar la carga y presentación de los datos.

  ```csharp
  private void RefreshUI()
  {
      // Lógica para optimizar el repintado de la UI
  }
  ```

**Referencia:** [Incremental Update Item Data for ListView-Based Controls in Windows 8.1](https://stackoverflow.com/questions/21605852/load-more-items-with-listview-windows-8-1)

## Cacheado de Imágenes

El cacheado de imágenes es fundamental para mejorar el rendimiento y reducir el consumo de ancho de banda al evitar descargas repetidas de las mismas imágenes.

**Estrategias de Cacheado:**

* **Cacheado en Memoria:**

  Utilizar estructuras de datos en memoria para almacenar imágenes temporalmente durante la sesión de la aplicación.

  ```csharp
  public class ImageCache
  {
      private readonly Dictionary<string, BitmapImage> _cache = new Dictionary<string, BitmapImage>();

      public BitmapImage GetImage(string uri)
      {
          if(_cache.ContainsKey(uri))
              return _cache[uri];

          var image = new BitmapImage(new Uri(uri));
          _cache.Add(uri, image);
          return image;
      }
  }
  ```
* **Cacheado Persistente:**

  Almacenar imágenes en el almacenamiento local para mantenerlas entre sesiones de la aplicación.

  ```csharp
  public async Task<StorageFile> GetCachedImageAsync(string uri)
  {
      string fileName = Path.GetFileName(uri);
      StorageFolder cacheFolder = ApplicationData.Current.LocalCacheFolder;
      try
      {
          return await cacheFolder.GetFileAsync(fileName);
      }
      catch (FileNotFoundException)
      {
          // Descargar y guardar la imagen
          var httpClient = new HttpClient();
          var imageBytes = await httpClient.GetByteArrayAsync(uri);
          return await cacheFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
      }
  }
  ```

**Referencia:** [CacheMode in UWP](https://learn.microsoft.com/es-es/uwp/api/windows.ui.xaml.uielement.cachemode)

## Mejora de Rendimiento para GridView

El control `GridView` es ampliamente utilizado para mostrar colecciones de datos en un formato de cuadrícula. Optimizar su rendimiento es esencial para manejar grandes conjuntos de datos sin afectar la experiencia del usuario.

**Técnicas de Optimización:**

* **Virtualización:**

  Asegurarse de que la virtualización esté habilitada para cargar solo los elementos visibles y reciclar los controles cuando no son necesarios.

  ```xml
  <GridView
      ItemsSource="{Binding Projects}"
      IsItemClickEnabled="True"
      VirtualizingStackPanel.VirtualizationMode="Recycling">
      <!-- Template -->
  </GridView>
  ```
* **Simplificación de Templates:**

  Mantener las plantillas de los ítems lo más simples posible para reducir la complejidad del renderizado.

  ```xml
  <GridView.ItemTemplate>
      <DataTemplate>
          <StackPanel>
              <Image Source="{Binding ImageUri}" Width="100" Height="100"/>
              <TextBlock Text="{Binding Name}" FontSize="14"/>
          </StackPanel>
      </DataTemplate>
  </GridView.ItemTemplate>
  ```
* **Uso de Imágenes Eficientes:**

  Utilizar formatos de imagen optimizados y reducir el tamaño de las imágenes para acelerar su carga y renderizado.

## CacheMode

El `CacheMode` es una propiedad que controla cómo se cachea un elemento visual. Utilizarlo correctamente puede mejorar significativamente el rendimiento de la aplicación al reducir la cantidad de recursos que necesitan ser renderizados repetidamente.

**Configuración del CacheMode:**

```xml
<Rectangle Width="200" Height="100" Fill="Blue" CacheMode="BitmapCache"/>
```

**Tipos de CacheMode:**

* **BitmapCache:** Cachea el elemento como una imagen de mapa de bits, lo que es útil para elementos que no cambian frecuentemente.
* **None:** No se realiza cacheado, ideal para elementos que cambian constantemente.

**Referencia:** [CacheMode in UWP](https://learn.microsoft.com/es-es/uwp/api/windows.ui.xaml.uielement.cachemode)

## Helpers

Los *helpers* son clases o métodos que facilitan tareas comunes en la aplicación, como el manejo de eventos complejos o la manipulación de datos. Utilizar helpers adecuados puede simplificar el código y mejorar el rendimiento general.

**Ejemplo de HoldingHelper:**

El `HoldingHelper` se utiliza para manejar eventos de sostenido en listas, permitiendo acciones rápidas como llamar o enviar un correo electrónico directamente desde la interfaz.

```csharp
public static class HoldingHelper
{
    public static void OnHolding(object sender, HoldingRoutedEventArgs e)
    {
        var listViewItem = sender as ListViewItem;
        if(listViewItem != null)
        {
            var task = listViewItem.Content as TaskItem;
            if(task != null)
            {
                EmailService.SendTaskEmail(task);
            }
        }
    }
}
```

**Uso en XAML:**

```xml
<ListView ItemsSource="{Binding Tasks}" SelectionMode="None">
    <ListView.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <TextBlock Text="{Binding Title}" FontSize="16"/>
                <TextBlock Text="{Binding DueDate}" FontSize="12" Foreground="Gray"/>
            </StackPanel>
            <ListViewItem.Holding="HoldingHelper.OnHolding"/>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>
```

## SemanticZoom y Agrupación de Tareas por Proyectos

El uso de `SemanticZoom` permite a los usuarios alternar entre una vista detallada y una vista agrupada de los datos, mejorando la navegabilidad en conjuntos de datos extensos.

**Implementación de SemanticZoom:**

```xml
<SemanticZoom>
    <SemanticZoom.ZoomedInView>
        <GridView ItemsSource="{Binding Tasks}">
            <!-- ItemTemplate -->
        </GridView>
    </SemanticZoom.ZoomedInView>
    <SemanticZoom.ZoomedOutView>
        <GridView ItemsSource="{Binding Projects}">
            <!-- Grouped ItemTemplate -->
        </GridView>
    </SemanticZoom.ZoomedOutView>
</SemanticZoom>
```

**Agrupación de Tareas por Proyectos:**

Agrupar tareas por proyectos facilita la organización y búsqueda de tareas dentro de cada proyecto.

```csharp
public class ProjectViewModel
{
    public string ProjectName { get; set; }
    public ObservableCollection<TaskItem> Tasks { get; set; }
}
```

```xml
<CollectionViewSource x:Name="GroupedTasks" IsSourceGrouped="True" ItemsPath="Tasks" Source="{Binding ProjectViewModels}">
    <CollectionViewSource.GroupDescriptions>
        <PropertyGroupDescription PropertyName="ProjectName"/>
    </CollectionViewSource.GroupDescriptions>
</CollectionViewSource>

<GridView ItemsSource="{Binding Source={StaticResource GroupedTasks}}">
    <!-- Grouped ItemTemplate -->
</GridView>
```

## Tabla 01 - Tipos de Tarea

| Tipo de tarea | Acción a realizar                                                                                                                                                                                    |
| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| CallTo        | ![](https://240651724-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfrvHBNivOTy0fVKROgzo%2Fuploads%2Fgit-blob-26dfe63aed723c3c9de1d7ae0d00ec3eb748a2e3%2Fimage1.png?alt=media) |
| EmailTo       | Enviar un correo electrónico relacionado con la tarea seleccionada.                                                                                                                                  |
| TalkTo        | Abrir WhatsApp, Telegram, SMS o crear una cita en el calendario.                                                                                                                                     |
| LaunchWith    | Crear una cita en el calendario o lanzar otra aplicación relacionada.                                                                                                                                |
| LinkTo        | Abrir el navegador web con una URL específica.                                                                                                                                                       |

## Integración del Control JumpList.xaml

Es importante integrar nuevos controles como `JumpList.xaml` de manera coherente con la estructura existente de la aplicación. Similar a cómo se integraron los controles `ListPlaceHolder` y `MultiSelectListView` en el **Capítulo 8**, se debe asegurar que `JumpList.xaml` funcione correctamente dentro del flujo de navegación y agrupación de tareas.

## Opción de Menú "Todas las Tareas (All tasks…)"

A diferencia de la funcionalidad mostrada en el **Capítulo 8**, donde se visualizan las tareas por proyecto, en esta sección implementaremos una opción de menú que permita acceder a todas las tareas de todos los proyectos simultáneamente.

**Implementación de la Opción de Menú:**

```xml
<MenuFlyout>
    <MenuFlyoutItem Text="Todas las tareas" Click="OnAllTasksClick"/>
</MenuFlyout>
```

```csharp
private void OnAllTasksClick(object sender, RoutedEventArgs e)
{
    Frame.Navigate(typeof(AllTasksPage));
}
```

En la página `AllTasksPage`, se mostrará una lista consolidada de todas las tareas, permitiendo una gestión más global de las mismas.

## Conclusión

Optimizar la rapidez y el rendimiento de una aplicación es esencial para proporcionar una experiencia de usuario satisfactoria. Mediante la implementación de técnicas como la paginación de servicios, la carga incremental de datos, el cacheado eficiente de imágenes, y la optimización de controles como `GridView`, podemos mejorar significativamente el rendimiento de nuestra aplicación. Además, el uso de herramientas y técnicas avanzadas como el `VisualStateManager`, `DataTriggerBehavior`, y comportamientos personalizados permite gestionar de manera eficiente los cambios en la interfaz de usuario, manteniendo la aplicación responsiva y eficiente incluso con grandes volúmenes de datos.

Al seguir estas prácticas, no solo aseguramos una aplicación rápida y eficiente, sino que también facilitamos el mantenimiento y escalabilidad futura, garantizando que nuestra aplicación pueda adaptarse a las necesidades cambiantes de los usuarios y del entorno tecnológico.
