Variare il layout di WPF in base alle performance del PC

di Cristian Civera, in Windows Presentation Foundation, XAML,

La novità principale di Windows Presentation Foundation è senza dubbio la sua capacità di creare interfacce ricche, con immagini, video, animazioni e oggetti 3D. Questo è possibile poiché il motore di rendering di WPF si base sulle DirectX e sfrutta quindi le scheda video che ormai ogni PC monta. Tuttavia questa potenzialità si scontra con le differenti configurazioni che l'applicazione che si sta sviluppando può trovarsi di fronte. Un medesimo layout può comportarsi in modo differente a seconda della GPU, della RAM e dalle tecnologie che la scheda video supporta. Dal lato sviluppatore invece animazioni e poligoni possono gravare sulle performance e rendere sgradevole l'esperienza dell'utente.

E' bene sapere che il motore di rendering ci garantisce nel bene o nel male che tutti gli elementi visuali saranno mostrati su ogni macchina e qual'ora mancasse la tecnologia hardware, questa viene compensata dal rendering software, gravando però sulla CPU.

E' ovvio che non tutte le applicazioni necessitano di particolari ornamenti e tutto dipende dallo scopo che esse hanno. Oltre a prestare quindi attenzione a questo aspetto, è possibile rendere intelligente l'applicazione e fornire un'esperienza migliore agli utenti che se lo possono permettere, mentre limitare effetti a chi non è grado di garantire certe performance, pur mantenendo l'utilità dell'applicazione stessa.

A tale scopo WPF mette a disposizione la classe RenderCapability (namespace System.Windows.Media) che contiene una sola proprietà Tier: un numero i cui bit indicano la capacità di rendering del thread attuale. Shiftando i bit, i valori possibili sono 0, 1 e 2. Zero indica che non è presente alcuna accelerazione hardware; uno che è presente un'accelerazione con le caratteristiche delle DirectX 7-9; due invece indica la piena capacità di rendering della scheda. Per maggiori informazioni si veda http://msdn2.microsoft.com/en-us/library/ms742196.aspx

In questo script si propone un modo per sfruttare questo parametro e influenzare l'applicazione. Si definisce per primo una classe con una DependencyProperty in sola lettura così da poter essere sfruttata direttamente nel markup XAML:

public static class RenderCapabilityManager
{
    private static readonly DependencyPropertyKey TierPropertyKey =
        DependencyProperty.RegisterAttachedReadOnly("Tier",
        typeof (int),
        typeof (RenderCapabilityManager),
        new FrameworkPropertyMetadata(RenderCapability.Tier >> 16));

    public static readonly DependencyProperty TierProperty = TierPropertyKey.DependencyProperty;

    public static int GetTier(DependencyObject element)
    {
        return (int) TierProperty.DefaultMetadata.DefaultValue;
    }
}

Ora si può utilizzare la proprietà definita all'interno in Style e Trigger così da cambiare il comportamento degli elementi. Per esempio un'immagine può essere animata se Tier è 2, oppure essere limitata nei frame con Tier a 1, oppure essere nascosta se Tier è 0. Per limitare i frame (i fotogrammi da mostrare in un secondo) è possibile usare la proprietà Storyboard.DesiredFrameRate da applicare su qualsiasi Timeline. Normalmente WPF cerca di renderizzare il massimo dei frame possibili mantenendosi sui 50/60 frame al secondo. Ecco quindi un esempio di Style per fare quanto descritto:

<Window x:Class="PerformanceTest.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:PerformanceTest"
    >
  <Window.Resources>

    <ParallelTimeline x:Key="enlargeAnimation" Storyboard.TargetProperty="Width">
      <DoubleAnimation From="100" To="200" RepeatBehavior="Forever" Duration="0:0:2" AutoReverse="True" />
    </ParallelTimeline>

    <Style x:Key="ButtonStyle" TargetType="{x:Type Image}">
      <Style.Triggers>
        <Trigger Property="local:RenderCapabilityManager.Tier" Value="0">
          <Setter Property="Visibility" Value="Hidden" />
        </Trigger>

        <Trigger Property="local:RenderCapabilityManager.Tier" Value="1">
          <Trigger.EnterActions>
            <BeginStoryboard>
              <Storyboard Storyboard.DesiredFrameRate="12">
                <StaticResource ResourceKey="enlargeAnimation" />
              </Storyboard>
            </BeginStoryboard>
          </Trigger.EnterActions>
        </Trigger>

        <Trigger Property="local:RenderCapabilityManager.Tier" Value="2">
          <Trigger.EnterActions>
            <BeginStoryboard>
              <Storyboard>
                <StaticResource ResourceKey="enlargeAnimation" />
              </Storyboard>
            </BeginStoryboard>
          </Trigger.EnterActions>
        </Trigger>

      </Style.Triggers>
    </Style>
  </Window.Resources>
  <Grid>

    <Image Source="http://gui.winfxitalia.com/images/winfxitalia.gif" Style="{StaticResource ButtonStyle}">
    </Image>

  </Grid>
</Window>

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti

I più letti di oggi