FullScreen

Date: martedì giugno 3, 2008
Posted in: Tutorials

Per alcune tipologie di applicazioni, la possibilità di poter essere eseguite in modalità fullscreen è molto importante, pensiamo ad esempio ad player di video (magari sfruttando il support al VC-1, la codifica per l’alta definizione) oppure una galleria fotografica.

In questo post vedremo come realizzare un pulsante che porti la nostra applicazione in modalità fullscreen.

L’oggetto a cui faremo riferimento è Application.Current.Host.Content
Questo oggetto ha due proprietà che possono essere lette in qualsiasi momento e sono

La terza proprietà rilevante per il nostro scopo è la IsFullScreen, quest’ultima è di tipo bool e può essere letta in qualsiasi momento ma può essere impostata soltanto dentro un evento di tipo:

  1. MouseLeftButtonDown
  2. MouseLeftButtonUp
  3. KeyDown
  4. KeyUp

Quindi se noi dentro il nostro metodo public Page() impostassimo la proprietà

 Application.Current.Host.Content.IsFullScreen = true;

per far si che la nostra applicazione vada subito in modalità fullscreen all’avvio, ebbene non succederebbe nulla.

Questa limitazione è stata voluta da Microsoft per impedire che applicazioni Silverlight possano passare alla modalità fullscreen senza nessun intervento da parte dell’utente finale.

Per verificare il funzionamento di quanto descritto creiamo un progetto di test con VisualStudio2008, il file Page.xaml sarà il seguente:

<UserControl x:Class="FullScreenTestSL.Page"
    xmlns="http://schemas.microsoft.com/client/2007" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Width="Auto" Height="Auto">
    <Grid x:Name="LayoutRoot" Background="White">
		<StackPanel>
			<TextBox x:Name="txtb1" Width="300" Height="30" Text=""></TextBox>
			<Button x:Name="btn1" Width="50" Height="30" MouseLeftButtonUp="btn1_MouseLeftButtonUp"></Button>
		</StackPanel>
	</Grid>
</UserControl>

Mentre il file Page.xaml.cs sarà:

?View Code CSHARP
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
 
namespace FullScreenTestSL
{
    public partial class Page : UserControl
    {
        public Page()
        {
            InitializeComponent();
            Application.Current.Host.Content.FullScreenChanged += new EventHandler(Content_FullScreenChanged);
 
            layoutUpdated(Application.Current.Host.Content.ActualHeight, Application.Current.Host.Content.ActualWidth);
        }
 
        void Content_FullScreenChanged(object sender, EventArgs e)
        {
            layoutUpdated(Application.Current.Host.Content.ActualHeight, Application.Current.Host.Content.ActualWidth);
        }
 
        private void btn1_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            Application.Current.Host.Content.IsFullScreen = !Application.Current.Host.Content.IsFullScreen;           
        }
 
        private void layoutUpdated(double height, double widht)
        {
            txtb1.Text = "Cur Height:" + height.ToString() + " Widht: " + widht.ToString();
        }
    }
}

Abbiamo associato all’evento MouseLeftButtonUp (che è uno degli eventi che sono abilitati a gestire la modalità fullscreen) il codice che modifica la proprietà IsFullScreen, in questo caso viene dato un effetto switch fullscreen/normalscreen alla pressione del pulsante.



I font in Silverlight

Date: venerdì maggio 9, 2008
Posted in: Tutorials

Quando definiamo un controllo TextBox o TextBlock Silverlight nativamente permette di specificare i seguenti Font:

Se vogliamo utilizzare un font diverso dobbiamo “embeddare” il font nella nostra applicazione.

Per fare ciò basta aggiungere al nostro progetto Silverlight, tramite il menu Add->Existing Item di Visual Studio, il file del Font e poi impostare le proprietà del file nel seguente modo
File Font Properties
Cioè impostando la proprietà Build Action in Resource e Copy to Output Dir in Copy Always.
Questo fa si che file del Font, in questo caso tahoma.ttf, venga inserito nel file xap dell’applicazione.

Per utilizzare ora il Font in un controllo testuale, ad esempio un TextBlock basta referenziare il file nel seguente modo

<TextBlock FontFamily=”tahomabd.ttf#Tahoma,sans-serif

dove nell’attributo FontFamily la prima parte, prima del cancelletto #, indica il nome del file che abbiamo embeddato, mentre la seconda parte indica la dicitura del font e delle sue eventuali caratteristiche che vogliamo utilizzare.

Quanto sopra ci permette di specificare un Font per controllo testuale durante la progettazione dell’interfaccia. Se invece vogliamo modificare un Font a Run-Time oppure specificarlo da codice (sempre considerando un Font diverso da quelli che Silverlight offre nativamente) possiamo procedere in due modi.

Il primo metodo consiste nell’utilizzare un Font Embedded, quindi aggiungiamo come abbiamo fatto sopra il file del font nella nostra applicazione, e poi tramite il seguente codice

?View Code CSHARP
  System.IO.Stream strm = this.GetType().Assembly.GetManifestResourceStream("NomeAssempbly.tahoma.ttf");
  miaTextBlock.FontSource = new FontSource(strm);

Possiamo specificare per la TextBlock miaTextBlock il font.

Il secondo metodo invece permette di utilizzare Font che non sono embeddati nell’applicazione, ma di caricare questi ultimi via HTTP. Utilizzando il seguente codice impostiamo il font del controllo miaTextBlock caricandolo direttamente dal sito che ospita l’applicazione.

?View Code CSHARP
  public Page()
  {
    InitializeComponent();
 
    WebClient fontWebClient = new WebClient();
    fontWebClient.OpenReadCompleted += new OpenReadCompletedEventHandler(fontWebClient_OpenReadCompleted);
    fontWebClient.OpenReadAsync(new Uri("http://www.silverlight-blog.it/tahoma.ttf", UriKind.Absolute));
  }
 
  void fontWebClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
  {
    miaTextBlock.FontSource = new FontSource(e.Result);
  }


Parametri di inizializzazione

Date: giovedì aprile 24, 2008
Posted in: Tutorials

Nel post precedente abbiamo visto che tramite il parametro opzionale initParams è possibile passare alla nostra applicazione dei parametri direttamente dalla pagine web che la ospita.

I parametri saranno delle coppie chiave=valore e saranno separati dalla virgola, una stringa di parametri potrebbe essere la seguente: nomeparametro1=valorepatametro1,nomeparametro2=valoreparametro2

Attualmente non è supportato l’escape dei caratteri speciali, sarà quindi opportuno utilizzare sono caratteri alfanumerici.

Il parametro initParams sarà gestibile ora dalla nostra applicazione web, ma attenzione non sarà leggibile dall’istanza della classe Page della nostra applicazione, ma sarà leggibile dall’istanza della classe App (quella sottolineata in rosso nell’immagine)
Classe App
Passare poi i parametri letti alla classe Page (che è quella che contiene il codice vero e proprio della nostra applicazione) sarà abbastanza semplice e possimo farlo in tre modi

  1. modificando la dichiarazione della nostra classe Page facendogli accettare dei parametri nel Costruttore
  2. aggiungendo un costruttore che accetti i parametri (quindi usando l’overloading)
  3. aggiungendo un attributo pubblico (o privato ma con un metodo pubblico per poterlo settare)

Nell’esempio seguente utilizzeremo il secondo metodo, vediamo quindi per primo il codice HTML che useremo per richiamare il plugin silverlight e per passare i parametri alla nostra applicazione

1
2
3
4
5
6
7
8
9
10
11
12
13
<div id="silverlightControlHost">
<object data="data:application/x-silverlight," type="application/x-silverlight-2-b1" width="100%" height="100%">
	<param name="source" value="ClientBin/PassaggioParametri.xap"/>
	<param name="onerror" value="onSilverlightError" />
	<param name="background" value="white" />
	<param name="initParams" value="nomeParam=ValoreParam" />
 
	<a href="http://go.microsoft.com/fwlink/?LinkID=108182" style="text-decoration: none;">
 			<img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none"/>
	</a>
</object>
<iframe style='visibility:hidden;height:0;width:0;border:0px'></iframe>
</div>

Vediamo ora invece il codice della nostra classe Page, supponiamo che textboxT1 sia un controllo textBox

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
    public partial class Page : UserControl
    {
        public Page()
        {
            InitializeComponent();
        }
 
        public Page(string valoreParametro)
        {
            InitializeComponent();
            textboxT1.Text = valoreParametro;
        }
    }

Infine per leggere correttamente i parametri passati dall’HTML modifichiamo il metodo Application_Startup della nosta classe App nel seguente modo

?View Code CSHARP
1
2
3
4
5
6
        private void Application_Startup(object sender, StartupEventArgs e)
        {
            string nomeParam = e.InitParams["nomeParam"];
            Page pagina = new Page(nomeParam);
            this.RootVisual = pagina;
        }

Quando il nostro esempio verrà eseguito il testo del nostro controllo textboxT1 sarà uguale a “ValoreParam”.



Includere Silverlight nelle pagine web

Date: mercoledì aprile 23, 2008
Posted in: Tutorials

Le applicazioni silverlight vengono facilmente integrate nelle pagine Web, più o meno come succede per quelle sviluppate in Flash. In questo post descriveremo come integrare nelle pagine web le applicazioni silverlight 2.0

Il tag HTML da utilizzare è il tag <object>, vediamo come utilizzarlo e quali sono i parametri che dobbiamo utilizzare, alcuni dei quali obbligatori, altri opzionali ed infine alcuni completamente personalizzabili (per passare dei parametri all’applicazione per esempio). Oltre al tag object è necessario anche l’utilizzo di un <iframe>.

Vediamo un esempio:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<script type="text/javascript">
    function onSilverlightError(sender, args) {
        if (args.errorType == "InitializeError")  {
            var errorDiv = document.getElementById("errorLocation");
            if (errorDiv != null)
                errorDiv.innerHTML = args.errorType + "- " + args.errorMessage;
        }
    }
    function onResizeHandler(sender, args) { }
</script>
<div id='errorLocation' style="font-size: small;color: Gray;"></div>
<div id="silverlightControlHost">
  <object data="data:application/x-silverlight," type="application/x-silverlight-2-b1" width="100%" height="100%">
  	<param name="source" value="ClientBin/PassaggioParametri.xap"/>
  	<param name="onerror" value="onSilverlightError" />
  	<param name="onResize" value="onResizeHandler" />
  	<param name="background" value="white" />
  	<param name="initParams" value="nomeParam=ValoreParam,nomeParam2=ValoreParam2" />
  	<a href="http://go.microsoft.com/fwlink/?LinkID=108182" style="text-decoration: none;">
   	  <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none"/>
  	</a>
  </object>
  <iframe style='visibility:hidden;height:0;width:0;border:0px'></iframe>
</div>

Per una corretta dichiarazione dobbiamo inserire nel tag object alcuni attributi e quest’ultimo dovrà contenere delle proprietà, vediamoli nel dettaglio.

Attributi obbligatori

Parametri obbligatori

Eventi obbligatori
silverlight permette di gestire alcuni eventi che può lanciare il plugin, questi ultimi vengono gestiti tramite funzioni javascript.

Parametri opzionali

Eventi opzionali
oltre ai due eventi visti sopra, silverlight ne espone altri tre sempre gestibili via javascript ma non obbligatori.

Parametri opzionali di Debug
i seguenti parametri ci se specificati forniscono dei dati utili per monitorare le nostre applicazioni in fase di sviluppo.

Infine abbiamo la parte del codice che permette di personalizzare l’installazione del plugin. Specificando infatti la parte:
<a href=”http://go.microsoft.com/fwlink/?LinkID=108182″ style=”text-decoration: none;”>
<img src=”http://go.microsoft.com/fwlink/?LinkId=108181″ alt=”Get Microsoft Silverlight” style=”border-style: none”/>
</a>

Facciamo in modo che se un utente non ha il plugin silverlight installato facciamo apparire un immagine (specificata nell’attributo src del tag IMG) che linka alla pagina (specificata dall’attributo href del tag A) dove è possibile scaricare il plugin ed installarlo.

Nei prossimi post vedremo nel dettaglio alcuni concetti che qui abbiamo solo accennato (passaggio di parametri alla nostra applicazione, creazione di un loader personalizzato etc.etc.) in quanto abbiamo preferito dare qui più una visione di insieme dei parametri e degli attributi che possono essere specificati quando inseriamo un’applicazione silverlight nelle nostre pagine web.



Gli stili

Date: domenica aprile 13, 2008
Posted in: Tutorials

Molti di voi ormai avranno già notato che il linguaggio XAML ha molti punti in comune con il linguaggio HTML. Entrambi possono essere definiti linguaggi di Markup descrittivi. Un ulteriore punto in comune tra i due linguaggi sono gli stili. Uno Style raggruppa un insieme di proprietà attribuendogli dei valori al fine di poterli condividere con uno o più elementi.

Nel seguente esempio vediamo dei bottoni definiti all’interno di un Canvas, ognuno dei quali con le stesse caratteristiche degli altri.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<Canvas Width="825" Height="645" Background="#FF000000">
  <Button Height="50" Width="100" Content="bottone 1" FontSize="15"  Canvas.Top="271" Canvas.Left="322" Background="red" Foreground="green" RenderTransformOrigin="0.5,0.5">
    <Button.RenderTransform>
      <RotateTransform Angle="-30"/>
    </Button.RenderTransform>
  </Button>
  <Button Height="50" Width="100" Content="bottone 2" FontSize="15"  Canvas.Top="271" Canvas.Left="442" Background="red" Foreground="green" RenderTransformOrigin="0.5,0.5">
    <Button.RenderTransform>
      <RotateTransform Angle="-30"/>
    </Button.RenderTransform>
  </Button>
  <Button Height="50" Width="100" Content="bottone 3" FontSize="15"  Canvas.Top="271" Canvas.Left="562" Background="red" Foreground="green" RenderTransformOrigin="0.5,0.5">
    <Button.RenderTransform>
      <RotateTransform Angle="-30"/>
    </Button.RenderTransform>
  </Button>
</Canvas>

produce
Bottoni Classici

Proviamo a definire uno Style per raggruppare le caratteristiche comuni di questi bottoni. Questo ci porterà 2 vantaggi. Il primo sarà quello di definire le caratteristiche comuni dei bottoni una sola volta, senza quindi doverle riscrivere per ogni bottone. Il secondo vantaggio sarà che quando dovremo modificare le caratteristice dei nostri bottoni basterà modificarle in quell’unico punto dove sono definite, lo Style appunto.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<Canvas Width="825" Height="645" Background="#FF000000">
  <Canvas.Resources>
    <Style x:Key="mioStile">
      <Setter Property="Button.Height" Value="50" />
      <Setter Property="Button.Width" Value="100" />
      <Setter Property="Button.FontSize" Value="15" />
      <Setter Property="Button.Background" Value="red" />
      <Setter Property="Button.Foreground" Value="green" />
      <Setter Property="Button.RenderTransform">
        <Setter.Value>
          <RotateTransform Angle="-30"/>
        </Setter.Value>
      </Setter>
    </Style>
  </Canvas.Resources>
 
  <Button Style="{StaticResource mioStile}" Canvas.Top="271" Canvas.Left="322" Content="Bottone1" />
  <Button Style="{StaticResource mioStile}" Canvas.Top="271" Canvas.Left="442" Content="Bottone2" />
  <Button Style="{StaticResource mioStile}" Canvas.Top="271" Canvas.Left="562" Content="Bottone3" />
</Canvas>

produce lo stesso risultato
Bottoni definiti con Style

Gli stili non devono necessariamente essere associati ad un determinato tipo di controllo. nell’esempio precedente abbiamo visto che i setter vanno ad agire sulle proprietà del controllo Button, ma noi possiamo benissimo essere più generici nel definire lo Style. Nel seguente esempio infatti definiamo uno stile che va a definire le proprietà per un generico controllo e poi istanziamo diversi controlli associandogli lo stile definito.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<Canvas Width="825" Height="645" Background="#FF000000">
  <Canvas.Resources>
    <Style x:Key="mioControlStile">
    <Setter Property="Control.Height" Value="50" />
    <Setter Property="Control.Width" Value="100" />
    <Setter Property="Control.Opacity" Value="1" />
    <Setter Property="Control.RenderTransform">
      <Setter.Value>
        <RotateTransform Angle="-30"/>
      </Setter.Value>
    </Setter>
    </Style>
  </Canvas.Resources>
 
  <Button Style="{StaticResource mioControlStile}" Content="Bottone1" Canvas.Top="271" Canvas.Left="322" />
  <TextBox Style="{StaticResource mioControlStile}" Text="TextBox" Canvas.Top="271" Canvas.Left="442"/>
  <CheckBox Style="{StaticResource mioControlStile}" Content="CheckBox" Foreground="white" Canvas.Top="271" Canvas.Left="562"/>
</Canvas>

produce
Style applicato su controlli diversi

Gli stili nello XAML sono quello che potrebbero essere i CSS per il linguaggio HTML, ci permettono quindi di separare la struttura della nostra applicazione dalla sua rappresentazione visiva.



Grafica vettoriale

Date: venerdì aprile 11, 2008
Posted in: Tutorials

Silverlight nativamente supporta la grafica vettoriale, gli oggetti base che fanno capo al Namespace degli Shapes sono i seguenti:

  1. Ellipse
    è una figura geometrica che rappresenta come dice il nome stesso un ellisse, in caso di stessa altezza e larghezza si ha un cerchio. E’ una figura chiusa, quindi possiede la propietà Fill che permette i specificare un riempimento (Brush) che può essere un gradiente, un colore o anche un ImageBrush (questi ultimi li abbiamo incontrati alla fine del post sulle immagini). Ha anche due propietà che sono comuni a tutti gli oggetti Shapes e sono Stroke e StrokeTickness, con la prima si può specificare il Brush con cui viene colorato il bordo del segmento che traccia la figura, la seconda invece ne indica lo spessore.
    Vediamo un esempio con un Ellipse in cui la proprietà Fill contiene un ImageBrush

    1
    2
    3
    4
    5
    6
    7
    
    <canvas width="333" height="266" background="#FF000000">
      <ellipse height="91" width="137" canvas.left="132" canvas.top="117" stroke="#FFFF1F1F" strokethickness="7">
        <ellipse.fill>
          <imagebrush imagesource="SilverLightLogo.png" stretch="Fill"></imagebrush>
        </ellipse.fill>
      </ellipse>
    </canvas>

    produce
    Ellipse

  2. Rectangle
    un rettangolo, oltre allestesse propietà dell’Ellipse ha anche due propietà particolari: RadiusX e RadiusY, che identificano rispettivamente la larghezza e l’altezza dell’ellisse che disegna gli angoli, in modo da poter avere degli angoli smussati invece che vivi.
    Vediamo un esempio di un Rectangle con le proprietà radius definite e con un ImageBrush in Fill

    1
    2
    3
    4
    5
    6
    7
    
    <canvas width="333" height="266" background="#FF000000">
      <rectangle height="54" width="106" canvas.left="46" canvas.top="22" stroke="#FF00FF1E" strokethickness="4" radiusx="5" radiusy="5">
        <rectangle.fill>
          <imagebrush imagesource="SilverLightLogo.png" stretch="Fill"></imagebrush>
        </rectangle.fill>
      </rectangle>
    </canvas>

    Produce
    Rectangle

  3. Line
    una semplice linea, definita tramite un punto di inizio (x,y) ed un punto di fine. Uniche proprietà sono Stroke e StrokeTickness.
    Esempio

    1
    2
    3
    
    <canvas width="333" height="266" background="#FF000000">
    <line x1="100" y1="10" x2="10" y2="100" canvas.left="194" canvas.top="25" stroke="#FFFFF500" strokethickness="3"></line>
    </canvas>

    produce
    Line

  4. Polygon
    una figura chiusa con un determinato numero di lati, può essere quindi un pentagono, un esagono, un ottagono e così via. Ha le stesse proprietà dell’Ellipse.
    Vediamo un esempio di un Polygon con soli tre lati

    1
    2
    3
    
    <canvas width="333" height="266" background="#FF000000">
    <polygon points="30,30 0,60 60,60" stroke="#FFFF0000" strokethickness="5" fill="#FFFDFF00" canvas.top="146" canvas.left="226"></polygon>
    </canvas>

    produce
    Polygon

  5. Polyline
    questo oggetto è simile a Polygon ma non necessariamente deve essere una figura chiua. Si può ottenere lo stesso risultato anche mettendo insieme delle Line.
    In questo esempio vediamo che nonostante la Polyline non è una figura chiusa è possibile specificare comunque la propietà Fill

    1
    2
    3
    
    <canvas width="333" height="266" background="#FF000000">
    <polyline points="60,180 120,160 180,180 130,130" stroke="#FF0015FF" strokethickness="4" canvas.top="-42" canvas.left="125" fill="#FFD81919"></polyline>
    </canvas>

    produce
    PolyLine

  6. Path
    questo oggetto definisce linee e figure complesse che possono essere composte da curve, archi e linee rette. Il Path possiede anche la proprietà Fill, quindi può essere riempito da un Brush.
    Anche in questo esempio pur non essendo una figura chiusa abbiamo specificato la proprietà Fill

    1
    2
    3
    
    <canvas width="333" height="266" background="#FF000000">
    <path height="71.965" width="114" canvas.left="189" canvas.top="111.291" fill="#FF00A5A4" stretch="Fill" stroke="#FFF900FF" strokethickness="4" data="M226,158 C235,168 213,188 251,175 C289,162 274,152.99991 259,146.9998 C244,140.99969 289.99979,130.99953 299.99976,151.99989"></path>
    </canvas>

    produce
    Path



Le immagini

Date: giovedì aprile 10, 2008
Posted in: Tutorials

Silverlight supporta due tipi di immagini, JPEG e PNG (anche con trasparenza). Le immagini possono essere visualizzate in vari modi, quello più diretto è l’utilizzo del control Image.
Guardiamo un esempio:
<Image Source=”silverlightlogo.jpg”>
il controllo in questo caso visualizza l’immagine nelle sue dimensioni originali (senza resize di nessun tipo) dato che non sono stati specificati i parametri Height e Width
img

Da sottolineare il fatto che i parametri Height e Width non si riferiscono strettamente alle dimensioni dell’immagine, ma piuttosto definiscono le dimensioni del rettangolo che conterrà l’immagine. L’immagine verrà poi disegnata all’interno di questo rettangolo seguendo la direttiva che viene specificata dal parametro Stretch (di default Stretch è impostato a None).
Il parametro Stretch può assumere i seguenti valori:

  1. None
    in questo caso l’immagine mantiene le sue dimensioni reali
  2. Fill
    l’immagine viene ridimensionata (senza mantenerne le proporzioni) per riempire tutto il rettangolo che contiene l’immagine
  3. Uniform
    l’immagine viene ridimensionata per riempire la maggior superficie possibile del rettangolo che la contiene mantenendo le proporzioni.
  4. UniformToFill
    l’immagine viene ridimensionata per riempire tutto il rettangolo che la contiene ma vengono mantenute le proporzioni tagliando l’immagine per farla rientrare nel rettangolo che la contiene

Vediamo degli esempi:
Stretch=None

1
2
3
<canvas height="120" background="#FF000000" width="200">
	<img source="SilverLightLogo.png" stretch="None" canvas.left="17.904" canvas.top="13.207" height="96" width="170" />
</canvas>

Produce il seguente effetto
None

Stretch=Fill

1
2
3
<canvas height="120" background="#FF000000" width="200">
  <img source="SilverLightLogo.png" stretch="Fill" canvas.left="17.904" canvas.top="13.207" height="96" width="170" />
</canvas>

Produce il seguente effetto
Fill

Stretch=Uniform

1
2
3
<canvas height="120" background="#FF000000" width="200">
  <img source="SilverLightLogo.png" stretch="Uniform" canvas.left="17.904" canvas.top="13.207" height="96" width="170" />
</canvas>

Produce il seguente effetto
Uniform

Stretch=UniformToFill

1
2
3
<canvas height="120" background="#FF000000" width="200">
  <img source="SilverLightLogo.png" stretch="UniformToFill" canvas.left="17.904" canvas.top="13.207" height="96" width="170" />
</canvas>

Produce il seguente effetto
UniformToFill

Un’altro modo per visualizzare le immagini è di definirle come ImageBrush, per riempire delle figure (Rectangle, Ellipse etc.etc.). Gli ImageBrush, come gli Image, hanno una propietà che permette di definire come l’immagine deve riempire la figura geometrica. Questa propietà si chiama Stretch.

Vediamo un esempio

1
2
3
4
5
6
7
<canvas height="120" background="#FF000000" width="200">
  <rectangle stroke="Black" strokethickness="1" canvas.left="11" canvas.top="8" height="97" width="173">
    <rectangle.fill>
      <imagebrush imagesource="SilverLightLogo.png" stretch="Fill"></imagebrush>
    </rectangle.fill>
  </rectangle>
</canvas>

Produce il seguente effetto
FillRectangle

Agendo sul parametro Stretch dell’ImageBrush si posso avere gli effetti elencati sopra.



Layout Controls

Date: mercoledì aprile 9, 2008
Posted in: Tutorials

I layout controls in Silverlight sono principalmente dei contenitori. In base al tipo di contenitore si avranno alcune proprietà che ci permettono di posizionare vari oggetti nello spazio a disposizione.

I layout controls sono in tutto 5, li descriveremo partendo da quelli più semplici.

  1. Canvas
    E’ il contenitore più semplice fra tutti, permette di posizionare oggetti (altri controlli) al suo interno in modo assoluto, specificando le coordinate Top e Left dell’angolo superiore sinitro di questi ultimi, nella figura seguente abbiamo un rettangolo blu dentro un canvas posizionato con Left 100 e top 80, naturalmente l’angolo superiore sinistro del canvas ha coordinate 0,0:
    Canvas Position
    Tradotto in Xaml quanto sopra:

    1
    2
    3
    4
    
    <canvas>
     <rectangle height="49" width="100" fill="#FF4883B5" stroke="#FF000000" canvas.top="80" canvas.left="100">
      </rectangle>
    </canvas>

    I Canvas possono contenere al loro interno un numero indefinito di oggetti.
    Infine il Canvas non permette il ridimensionamento del contenuto al suo interno, ma per ovviare a questo problema basta racchiudere il Canvas in un contenitore che permetta il ridimensionamento.

  2. Border
    Il Border è categorizzato come Layout Control anche se non lo è nel senso stretto del termine. Esso infatti non può essere utilizzato per posizionare oggetti nello spazio, dato che può contenere solo un oggetto al suo interno. Diciamo che viene utilizzato, come suggerisce il nome stesso, per fare da bordo-cornice per un altro controllo contenuto al suo interno.
  3. StackPanel
    Lo StackPanel è un contenitore che dispone i controlli figli uno sotto l’altro (se l’orientazione è impostata come verticale):

    1
    2
    3
    4
    5
    6
    
    <stackpanel height="178" width="141" orientation="Vertical">
     <button content="Button"></button>
     <button content="Button"></button>
     <button content="Button"></button>
     <button content="Button"></button>
    </stackpanel>

    genera:
    Stack Panel Veritcal
    oppure uno di fianco all’altro (se l’orientazione è impostata come orizzontale):

    1
    2
    3
    4
    5
    6
    
    <stackpanel height="178" width="141" orientation="Horizontal">
     <button content="Button"></button>
     <button content="Button"></button>
     <button content="Button"></button>
     <button content="Button"></button>
    </stackpanel>

    genera invece:
    StackPanel Horizontal

  4. ScrollViewer
    Lo ScrollViewer permette al contenuto di essere più grande del contenitore, e il contenuto può essere visualizzato agendo sulle barre di scrolling (verticale ed orizzontale). Il seguente codice:

    1
    2
    3
    4
    5
    6
    7
    8
    
    <scrollviewer height="100" width="100" horizontalscrollbarvisibility="Auto" verticalscrollbarvisibility="Auto">
    <stackpanel height="178" width="141" orientation="Horizontal">
     <button content="Button"></button>
     <button content="Button"></button>
     <button content="Button"></button>
     <button content="Button"></button>
    </stackpanel>
    </scrollviewer>

    Produce:
    ScrollViewer
    Come il Border anche lo ScrollViewer può contenere soltanto un oggetto.

  5. Grid
    Il Layout Control Grid è quello più complesso, permette di dividere l’area a disposizione in righe e colonne. La grandezza (intesa come larghezza o altezza) delle righe e delle colonne può essere definita in tre modi diversi:

    • Auto, in questo modo l’altezza/larghezza della riga o della colonna viene automaticamente ricavata dal controllo contenuto al suo interno.
    • inPixel, specificando numericamente la dimensione in pixel.
    • *, specificando asterisco seguito da un numero si utilizza proporzionalmente lo spazio a disposizione.

    Descriviamo come la dimensione delle righe per esempio possa essere definita in modo proporzionale.
    Il seguente XAML definisce una griglia con 3 righe, dove la prima riga ha altezza 1* che significa una quantità unitaria dello spazio a disposizione. La riga 2 invece ha un’altezza pari a 2* che indica due volte lo spazio a disposizione. Infine la terza riga ha un altezza pari a 3* che indica 3 volte lo spazio a disposizione. Quando viene disegnata la Grid, la sua altezza viene divisa in modo proporzionale sulle sue righe, e quindi la seconda riga sarà alta il doppio della prima, e la terza il triplo della prima:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    <grid>
    	<grid.rowdefinitions>
    		<rowdefinition height="1*">
    		<rowdefinition height="2*">
    		<rowdefinition height="3*">
    	</grid.rowdefinitions>
    	<button horizontalalignment="Left" margin="0,0,0,0" width="Auto" grid.rowspan="1" content="Button" grid.row="0"></button>
    	<button horizontalalignment="Left" margin="0,0,0,0" width="Auto" grid.rowspan="1" content="Button" grid.row="1"></button>
    	<button horizontalalignment="Left" margin="0,0,0,0" width="Auto" grid.rowspan="2" content="Button" grid.row="2"></button>
    </grid>

    produce:
    Grid
    Ridimensionando una grid il contenuto al suo interno viene automaticamente ridisposto per adattarsi alle nuove dimensioni.

In questo post sono stati descritti gli aspetti principali dei Layout Controls, ognuno di essi ha molte proprietà che ne caratterizzano la visualizzazione finale o gli effetti sugli oggetti che contengono.



Cross Domain Policy

Date: martedì aprile 8, 2008
Posted in: Tutorials

Uno dei punti di forza del Silverlight è quello di rendere l’accesso e la lettura di servizi web molto facilitato. Possiamo per esempio accedere e leggere con facilità Web Services o file XML. Ma vi sono delle problematiche da tenere presente per evitare di impazzire quando un applicativo deve essere spostato dall’ambiente di sviluppo all’ambiente di produzione.

Supponiamo di avere un nostro sito web con un suo dominio ben definito (www.silverlight-blog.it). Su questo sito carichiamo una applicazione in Silverlight che tramite una semplice chiamata http legge gli RSS della prima pagina de IlSole24Ore.com (http://www.ilsole24ore.com/rss/primapagina.xml) per poi visualizzarli.
Il codice che si occupa di questo è il seguente:

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public partial class Page : UserControl
{
	WebClient rssReadService;
	public Page()
	{
		InitializeComponent();
 
		rssReadService = new WebClient();
		rssReadService.DownloadStringCompleted += new DownloadStringCompletedEventHandler(rssReadService_DownloadStringCompleted);
		ssReadService.DownloadStringAsync(new Uri("http://www.ilsole24ore.com/rss/primapagina.xml"));
	}
 
	void rssReadService_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
	{
		if (e.Error == null)
		{
			XDocument xmlDoc = XDocument.Parse(e.Result);
			// Di seguito il codice per gestire il documento XML e visualizzarlo
		}
	}
}

Facendo partire il debug dell’applicazione e analizzando tramite uno sniffer HTTP le chiamate che vengono effettuare al dominio remoto (ilsole240re.com) vediamo che avvengono in questo ordine:

  1. Il primo url ad essere richiesto da Silverlight è http://www.ilsole24ore.com/clientaccesspolicy.xml
    Se il file clientaccesspolicy.xml viene trovato ne viene analizzato il contenuto ed in base a quest’ultimo si procede alla chiamata 3
  2. Se il primo url non restituisce il file richiesto allora viene effettuata una seconda richiesta:
    http://www.ilsole24ore.com/crossdomain.xml
    Se il file crossdomain.xml esiste quest’ultimo viene analizzato per verificare se è possibile effettuare la richiesta 3
  3. Questa è la richiesta effettiva che abbiamo impostato noi nel codice
    http://www.ilsole24ore.com/rss/primapagina.xml
    tramite la quale possiamo leggere i feed rss della prima pagina del sole24ore.

Perchè invece di aprire direttamente l’url al punto 3 vengono effettuate le chiamate precedenti??

La risposta è abbastanza semplice e questa problematica viene definita come Cross Domain Policy.
Quando il proprietario di un sito web espone un servizio tramite il protocollo HTTP (che può essere unWebService, un RSS, un semplice file XML etc.etc.) può decidere se quest’ultimo può essere letto anche da applicazioni web (caso di Silverlight e di Flash) che risiedono su un dominio diverso da quello dove il servizio stesso è pubblicato. Quindi se chi espone il servizio non concede esplicitamente il permesso quest’ultimo è negato per default.
Il modo per permettere alle applicazioni web di accedere ai servizi è quello di utilizzare i file cross domain (introdotti da Flash) oppure i file clientaccesspolicy.xm (introdotti da Silverlight).
I file sopra descritti possono dare il permesso di accedere ai servizi esposti in modo molto granulare, specificando ad esempio da quale dominio le applicazioni web possono accedere. Se io creo un file chiamato clientaccesspolicy.xml sul sito www.ilsole24ore.com con questo contenuto:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
<access-policy>
  <cross-domain-access>
<policy>
      <allow-from>
        <domain uri="pippo.com">
      </domain>
      <grant-to>
        <resource path="/" include-subpaths="true">
      </resource>
    </grant-to>
  </allow-from>
</policy>
</cross-domain-access></access-policy>

Voglio indicare che tutte le applicazioni Silverlight (o che usano il file clientaccesspolicy per richiedere l’autorizzazione) che risiedono sul dominio pippo.com possono accedere ai servizi presenti sul mio sito (ilsole24ore.com).

Attualmente sul sito del sole24ore è presente questo file crossdomain.xml:

1
2
3
<cross-domain-policy>
<allow-access-from domain="ilsole24ore.com" to-ports="80"></allow-access-from>
</cross-domain-policy>

Che indica che sono autorizzati ad accedere ai servizi esposti dal sito soltanto le web application che risiedono sul dominio ilsole24ore.com (le web app del sole24ore stesso).
Questo file sembrerebbe ridondante dato che le web app che già risiedono sullo stesso dominio in cui viene esposto il servizio possono accedervi, ma in questo caso il file è stato creato per permettere per esempio ad un applicazione flash che risiede su finanza.ilsole24ore.com di poter accedere ad un servizio che risiede si www.ilsole24ore.com

Alla luce di quanto sopra il codice indicato all’inizio dell’articolo, che voleva leggere gli rss, è destinato a sollevare un errore e quindi la nostra condizione:

if (e.Error == null)

Fallisce.

Il comportamento di Silverlight però allo stato attuale differisce da quello di Flash in modo sostanziale. Attualmente Silverlight 2 Beta 1 interroga i files dei permessi cross domain soltanto quando bisogna accedere ad un servizio web (web service, xml, rss etc.etc), invece per quanto riguarda i files multimediali (mp3, jpg, png, wmv…) possono essere liberamente caricati da un dominio diverso da quello su cui gira l’applicazione silverlight.

Quindi se nell’esempio sopra, invece di accedere al file primapagina.xml, avessi cercato di accedere ad un file immagine.jpg o ad un file audio.mp3 non avrei avuto nessun problema.



Creare un progetto Silverlight con VisualStudio 2008

Date: martedì aprile 8, 2008
Posted in: Tutorials

Il primo passo per iniziare a sviluppare una applicazione Silverlight è quello di creare un progetto tramite Visual Studio. Praticamente il progetto può essere creato anche direttamente da Blend, ma in questo caso non sarà possibile fare il debug dell’applicazione tramite Visual Studio. Vi sono inoltre degli accorgimenti durante la creazione di quest’ultimo che faciliteranno la gestione del ciclo di vita dell’applicazione.
Vediamo passo passo come procedere :

  1. Dal Menu di VS selezionare File->New->Project e dalla schermata di creazione del progetto, come in figura, selezionare sotto Project Types: Silverlight e sotto Templates selezionare Silverligh Application.
    Creazione Progetto Silverlight
  2. Dopo aver premuto OK nella schermata precedente VisualStudio ci chiede dove vogliamo che venga ospitata l’applicazione, le scelte a disposizione sono due. La prima aggiunge alla soluzione che stiamo creando un progetto Web .NET che contiene già le pagine con i tag necessari per richiamare l’applicazione Silverlight. La seconda (questa seconda opzione viene utilizzata implicitamente da Blend quando si crea un nuovo progetto Silverlight) invece aggiunge al progetto Silverlight solo una pagina web HTML che contiene i tag per richiamare l’applicazione Silverlight.
    Le due scelte sembrano simili, ma solo con la prima si potrà poi effettuare il debug con VS. Quindi selezioniamo la prima opzione nella seguente schermata.
    Selezione Web Solution
  3. Dopo aver premuto OK VisualStudio apre direttamente il progetto appena creato. Nel box del solution explorer vedremo la struttura della nostra solution:
    Solution Explorer
    noteremo quindi che la solution contiene 2 progetti. Il primo rappresentato è il progetto web che contiene 3 file (Default.aspx, NomeSoluzioneTestPage.aspx, NomeSoluzioneTestPage.html). La prima è una pagina vuota mentre la seconda e la terza sono due pagine che contengono entrambe i tag (sia in .NET che in semplice HTML) per richiamare la nostra applicazione Silverlight.

Adesso abbiamo creato il nostro progetto. Premendo F5 verrà eseguito correttamente il debug tramite il web server integrato in VisualStudio. Sarà inoltre possibile aprire normalmente la soluzione tramite Blend.