Embed resources the right way in Windows Phone 7


Anche se sviluppare un applicazione su Windows Phone 7 è, direi al 80%, del tutto simile allo sviluppo di un applicazione Silverlight 3.0, non dobbiamo dimenticarci di quel 20% che è sicuramente quello destinato a farci penare prima del rilascio, in quel 20% oltre al Tombstoning aggungerei sicuramente l’aspetto performances perchè, non dimentichiamolo, abbiamo comunque a che fare con un dispositivo e non con un personal computer.
Un esempio dove un dettaglio può far la differenza è la modalità di embedding di eventuali risorse all'interno di un progetto WP7.
Da questo punto di vista gli strumenti di sviluppo (Blend 4 e Visual Studio 2010) non sono dalla nostra parte in quanto quando aggiungiamo una qualsiasi risorsa al progetto questi impostano la relativa Build Action a Resource.
A prima vista nulla di strano, se non fosse che, come sapete, le applicazioni WP7 per essere scaricate devono passare dal MarketPlace e questo processo ha come conseguenza il fatto che le assemblies presenti nello xap vengono firmate e la firma viene verificata al primo startup del programma nel telefono (nella beta la verifica avviene ad ogni startup)
Se conoscete come avviene il processo di verifica della firma saprete che questo è tanto più lungo quanto maggiore è la dimensione dell’assembly  percui se all’interno di un assembly abbiamo embeddato un immagine da 5 MB questa influirà negativamente sul primo startup.
La soluzione? Impostare la Build Action delle risorse a Content anzichè Resource, in questo modo, dal punto di vista dell’utilizzo sia a livello di codice che a livello XAML non cambia nulla, ma l’avvio dell’applicazione è stato sicuramente migliorato.

Technorati Tags: ,

author: Corrado Cavalli | posted @ lunedì 23 agosto 2010 21.03 | Feedback (0)

WPF Ribbon


Finalmente la tanto attesa nuova versione del controllo ribbon per WPF è disponibile: l’interfaccia applicativa è stata completamente rivista e, yes!, l’oggetto RibbonButton supporta ICommand.
In questo post di Pete Brown trovate un tutorial sul suo utilizzo: http://10rem.net/blog/2010/08/02/announcing-microsoft-ribbon-for-wpf-rtw

Download page: http://www.microsoft.com/downloads/details.aspx?FamilyID=2BFC3187-74AA-4154-A670-76EF8BC2A0B4&displaylang=en
Documentazione: http://msdn.microsoft.com/en-us/library/ff799534.aspx

Technorati Tags:

author: Corrado Cavalli | posted @ martedì 3 agosto 2010 6.48 | Feedback (2)

WP7: Launchers and Choosers


Le applicazioni Windows Phone 7 vengono eseguite nella propria sandbox e non hanno accesso diretto alle funzionalità del telefono come ad esempio: l’elenco dei contatti, l’invio degli SMS oppure l’invio di una semplice telefonata.
Per far questo bisogna utilizzare delle opportune API definite nella documentazione col nome di Launchers e Choosers, già dal nome dovreste intuire che queste sono a tutti gli effetti delle applicazioni built-in (non a caso le relative classi stanno in Microsoft.Phone.Task) le quali si differenziano dal fatto che i Choosers, a differenza dei Launchers, possono ritornare delle informazioni all’applicazione chiamante.
Nella documentazione MSDN trovate l’elenco dei Launchers e Choosers disponibili, quello che però bisogna tenere in considerazione quando si utilizzando queste funzionalità  sono due aspetti fondamentali:

  • Essendo Launchers e Choosers delle applicazioni, quando lanciate, queste “spengono” (o meglio mandano in Tombstoning") l’applicazione chiamante, ovvero la nostra.
    Se volete saperne di più andate qui
  • In caso di Choosers se volete, come presumo, gestire le informazioni ritornate all’applicazione il codice va scritto in un determinato modo.

Vediamo un caso banale di utilizzo di un Launcher: per capire cosa succede ho inserito il seguente codice in App.xaml.cs:

private void Application_Activated(object sender, ActivatedEventArgs e)
{
Debug.WriteLine("Activated");
}

private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
Debug.WriteLine("Deactivated");
}

e all’interno dell’evento Click di un pulsante ho scritto:

private void button1_Click(object sender, RoutedEventArgs e)
{
SearchTask searchTask = new SearchTask { SearchQuery = "Windows Phone 7" };
searchTask.Show();
Debug.WriteLine("Completed");
}

Lanciando il progetto e premendo il pulsante ecco quello che appare nell’emulatore:

image

Ma sopratutto, questo è quello che viene tracciato nella Output window:

image 

Questo dovrebbe già farvi capire che eseguire del codice dopo che un Launcher è stato completato non è poi così banale, tenendo presente che, come già ciatato nei posts precedenti, la nostra applicazione potrebbe anche non essere più ripristinata.

Vediamo ora un semplice caso di Chooser: La documentazione indica che, se vogliamo che il meccanismo di ripristino post-tombstoning sia in grado di invocare correttamente l’evento Completed di un Chooser è necessario che:

  • L’istanza del Chooser sia definita a livello di ApplicationPage.
  • La sottoscrizione dell’evento avvenga nel costruttore della pagina stessa.

in pratica qualcosa tipo:

public partial class MainPage : PhoneApplicationPage
{
PhoneNumberChooserTask task = new PhoneNumberChooserTask();

public MainPage()
{
InitializeComponent();
task.Completed += new EventHandler<PhoneNumberResult>(task_Completed);
}

private void button2_Click(object sender, RoutedEventArgs e)
{
task.Show();
}

private void task_Completed(object sender, PhoneNumberResult e)
{
if (e.Error == null) MessageBox.Show(e.PhoneNumber);
}
}
Così facendo, se avete dei numeri memorizzati nel device/emulatore (se non li avete potete aggiungerli usando il SavePhoneNumberTask) avrete la possibilità di selezionarne uno e, premuto F5 quando dopo la selezione lo schermo dell’emulatore diventa nero, vedrete eseguire il codice all’interno del gestore task_Completed.
 
Nulla di spaventosamente complicato, anzi, ma sicuramente l’intervento del Tombstoning implica,anche in questo caso, una certa attenzione in caso di utilizzo di queste API nei nostri programmi Windows Phone.
 

author: Corrado Cavalli | posted @ domenica 1 agosto 2010 19.21 | Feedback (3)

Hosting Silverlight Cross Domain Applications


Pur non essendo un caso frequente, può capitare di dover ospitare un applicazione Silverlight proveniente da un dominio diverso dalla pagina host.
Un esempio può essere: Pagina html ospitata nel domino foo.com la quale ha al suo interno qualcosa del genere:

<div id="silverlightControlHost">
<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
<param name="source" value="http://www.anothersite.com/myapp.xap"/>
<param name="onError" value="onSilverlightError" />
<param name="background" value="white" />
<param name="minRuntimeVersion" value="4.0.41108.0" />
<param name="autoUpgrade" value="true" />
<a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=4.0.41108.0" style="text-decoration:none">
<img src="http://go.microsoft.com/fwlink/?LinkId=161376" alt="Get Microsoft Silverlight" style="border-style:none"/>
</a>
</object>
<iframe id="_sl_historyFrame" style="visibility:hidden;height:0px;width:0px;border:0px"></iframe></div>

Il fatto che l’applicazione provenga da un dominio diverso (anothersite.com nello snippet precedente) genera una situazione di cross-domain hosting la quale può creare qualche problema di funzionamento (o non permettere nemmeno lo start dell’applicazione in alcuni casi)

La soluzione è in realtà abbastanza semplice e consiste nell’impostare a true il parametro enableHTMLAccess del plug-in in questo modo:

 

<param name="enableHtmlAccess" value="true" />
 
il quale viene automaticamente impostato a true quando l’applicazione proviene dallo stesso dominio della pagina host.
Dalla documentazione sembrerebbe che questo parametro abiliti esclusivamente l’interazione tra l’applicazione e il DOM della pagina host, in realtà dalle prove effettuate oggi questa controlla anche l’interazione con tutto il browser stack, percui, se come nel mio caso utilizzate la classe WebClient per interagire col server la chiamata viene immediatamente interrotta con le relative conseguenze per l’intera applicazione.
 
Non capita spesso, ma se capita, ricordatevi questo post…
 

author: Corrado Cavalli | posted @ giovedì 29 luglio 2010 19.19 | Feedback (0)

WP7: Page Navigation


In Windows Phone 7 ogni singola PhoneApplicationPage è automaticamente ospitata all’interno di un PhoneApplicationFrame che viene impostato come RootVisual allo startup dell’applicazione all’interno del metodo CompleteInitializePhoneApplication presente in App.xaml.cs (l’evento RootFrame.Navigated scatta dopo che lo SplashScreen è stato sostituito con la pagina iniziale dell’applicazione)
Visto che PhoneApplicationFrame estende la classe Frame introdotta in Silverlight 3.0 la navigazione da una pagina all’altra avviene esattamente secondo la stessa modalità, quindi per  navigare da MainPage a AnotherPage è sufficiente usare la classe NavigationService.

private void OnClick(object sender, RoutedEventArgs e)
{
NavigationService.Navigate(new Uri("/AnotherPage.xaml", UriKind.Relative));
}

Anche in Windows Phone è presente la classe UriMapper da utilizzare nel caso non vogliate legare il codice direttamente al nome della pagina (personalmente vedo meglio il suo utilizzo in un applicazione Silverlight vista la mancanza del deep linking in Windows Phone).
In Blend4 for Windows Phone Beta la navigazione è ancora più semplice grazie alla presenza di una NavigateToPageAction accessible direttamente dall’apposito menu contestuale NavigateTo

image

In breve, nulla di nuovo per chi è già un “Silverlighter”…

Technorati Tags: ,

 

   

author: Corrado Cavalli | posted @ giovedì 29 luglio 2010 10.44 | Feedback (0)

WP7: Application Lifecycle and Tombstoning


Se è vero che  sviluppare un applicazione per Windows Phone 7, conoscendo già Silverlight, non è poi così difficile in realtà ci sono una lunga serie di dettagli da conoscere perchè, non dimentichiamoci, l’applicazione non sta girando su un PC (quindi l’utilizzo corretto delle risorse diventa ancora più importante) ed è in esecuzione su un sistema operativo con caratteristiche proprie.
Una di queste è  il fatto che, almeno in questa versione, Windows Phone 7 non è un sistema operativo multi-tasking, per i vari motivi che sicuramente già conoscete.

Per lo sviluppatore di applicazioni Windows Phone 7 Il fatto di non essere multi-tasking implica un dettaglio tutt’altro che trascurabile: A differenza di ciò che accade con un applicazione WPF/Silverlight o Windows Forms dove l’applicazione inizia e termina secondo uno schema ben definito,  in Windows Phone 7 possono essere terminate ed eventualmente risvegliate più volte dal sistema operativo stesso durante la normale esecuzione Per aiutarci nel gestire questo probabile  susseguirsi di eventi di avvio, deattivazione, riattivazione e chiusura abbiamo a disposizione 4 eventi: Launched, Deactivated, Activated e Closed gentilmente messi a disposizione dalla classe PhoneApplicationService la quale grazie all’implementazione dell’interfaccia IApplicationService introdotta con Silverlight 3.0  viene gestita come LifeTimeObject dal template di Visual Studio 2010 in questo modo:

<Application.ApplicationLifetimeObjects>
        <!--Required object that handles lifetime events for the application-->
        <shell:PhoneApplicationService 
            Launching="Application_Launching" Closing="Application_Closing" 
            Activated="Application_Activated" Deactivated="Application_Deactivated"/>
    </Application.ApplicationLifetimeObjects>

dal quale si evidenzia che in App.xaml.cs il template mette  a disposizione i 4 eventi precedentemente citati.

Per capirne di più, creiamo  una nuova  applicazione Windows Phone in Visual Studio 2010 e andiamo ad aggiungere nei vari gestori  delle semplici chiamate a Debug.WriteLine così da capire come questi si susseguono:

private static string id = Guid.NewGuid().ToString();
 
 private void Application_Launching(object sender, LaunchingEventArgs e)
 {
    Debug.WriteLine("Launching {0}", App.id);
 }
 
 private void Application_Activated(object sender, ActivatedEventArgs e)
 {
    Debug.WriteLine("Activated {0}", App.id);
 }
 
 private void Application_Deactivated(object sender, DeactivatedEventArgs e)
 {
    Debug.WriteLine("Deactivated {0}", App.id);
 }
 
 private void Application_Closing(object sender, ClosingEventArgs e)
 {
    Debug.WriteLine("Closing {0}", App.id);
 }

A questo punto, premendo F5 nella output window possiamo notare come sia l’evento  Launching il primo ad essere  invocato allo startup dell’applicazione:

image

Premendo il tasto Back dell’emulatore, non essendoci nulla nella history del telefono/emulatore relativa alla nostra applicazione, questa viene terminata e nella output window è possibile vedere elencato l’evento Closing:

image

Rilanciamo l’applicazione e rivedremo di nuovo l’evento Launching (associato ad un altro Guid essendo a tutti gli effetti un altra istanza) ma ora premendo il tasto Home dell’emulatore vedremo questa volta nella output window l’evento Deactivated

image

Qual’è la differenza tra Closing e Deactivated?: In entrambi i casi l’applicazione è stata terminata e quindi scaricata dalla memoria, la differenza è che in questo caso il sistema operativo oltre a terminare l’applicazione ha anche memorizzato delle informazioni legate alla nostra applicazione, potremmo quidi dire: “Terminata con riserva” oppure usare il termine ufficiale Tombstoned.

Se ora premiamo il tasto Back dell’emulatore, essendo la nostra applicazione presente nel Back stack dell’emulatore , grazie anche alla presenza delle informazioni precedentemente salvate, può essere “resuscitata”.
Prima di controllare se ciò accade veramente e doverosa una precisazione: Un applicazione recuperata dopo un Tombstoning è, a tutti gli effetti, una nuova istanza e, visto che in questo caso abbiamo l’emulatore e il relativo debugger di mezzo, per ripristinare la stessa situazione precedente al Tombstoning è necessario attaccare il debugger, quindi per verificare che l’evento segnalato nella debug window sia Activated anzichè Launching dobbiamo:

  • Premere il tasto Back dell’emulatore, otterremo quindi che lo schermo diverrà nero.
  • Premere entro 10 secondi il tasto F5 di Visual Studio in modo che il debugger venga attaccato alla nuova istanza (10 sec è il tempo max concesso ad un applicazione per riattivarsi)

Fatto questo nella output window vedremo elencato l’evento Activated

image

Notate come il GUID sia cambiato, questo perchè l’istanza con cui abbiamo a che fare non ha nulla a che fare con quella precedente quindi tutto lo stato pre-Tombstoning è andato completamente perso.
La domanda ora è : se in entrambi i casi l’applicazione viene terminata e scaricata dalla memoria qual’è la differenza tra Terminating e Deactivated?

Potremmo dire che in caso di Deactivated  “Non tutto è perduto”: Innanzitutto è vero che a tutti gli effetti viene rilanciata una nuova istanza dell’applicazione ma questa, grazie alle informazioni memorizzate in precedenza, è in grado ad esempio di istanziare automaticamente la pagina attiva nel momento del TombStoning.
Verifichiamolo andando ad aggiungere alla nostra applicazione di prova  una nuova pagina RunTask:

image

e aggiungiamo alla pagina principale un pulsante che ci permetterà di navigare alla pagina stessa:

image

 

 

private void OnRunTask(object sender, RoutedEventArgs e)
{
  Uri uri = new Uri("/RunTask.xaml", UriKind.Relative);
  NavigationService.Navigate(uri);
}

Ora rilanciamo l’applicazione premendo F5, premiamo il pulsante RunTask e, mentre siamo nella pagina RunTask premiamo il tasto Home dell’emulatore: L’applicazione verrà deattivata (TombStoned)
Premiamo ora il tasto Back dell’emulatore per ripristinare l’applicazione, ricordando di premere F5 in Visual Studio entro 10 secondi non appena lo schermo diventa nero: Non solo vedremo l’evento Activated ma vedremo apparire non la pagina principale ma direttamente la pagina RunTask a conferma che la pagina attualmente aperta è tra le informazioni memorizzate in caso di Tombstoning.

Prima di proseguire un altro paio di precisazioni:

  • In caso di riattivazioni le eventuali finestre aperte in precedenza non vengono più automaticamente istanziate.
  • Se l’utente esegue una lunga serie di operazioni percui il  Back stack viene riempito, può essere che, premendo ripetutamente il tasto Back, l’applicazione non venga mai più ripristinata.

Le applicazioni Windows Phone 7 devono perciò essere pensate per lavorare secondo questo modo “transiente”.

Supponiamo che la pagina RunTask abbia al proprio interno una TextBox che permette di inserire il termine che vogliamo cercare nel MarketPlace, ovvero qualcosa tipo:

image
namespace Wp7ApplicationLifeCycle
{
   using Microsoft.Phone.Tasks;
 
   public partial class RunTask : PhoneApplicationPage
   {
      public RunTask()
      {
         InitializeComponent();
      }
 
      private void OnClick(object sender, RoutedEventArgs e)
      {
         MarketplaceSearchTask marketplaceSearchTask = new MarketplaceSearchTask();
         marketplaceSearchTask.SearchTerms = txtSearch.Text;
         marketplaceSearchTask.Show();
      }
   }
}

Rilanciamo l’applicazione, navighiamo di nuovo verso RunTask, scriviamo qualcosa all’interno della TextBox, premiamo il tasto Home dell’emulatore e, successivamente, premiamo il tasto Back per riattivarla. Risultato: Siamo di nuovo nella pagina RunTask ma il contenuto della TextBox cosi come altri eventuali dati inerenti allo stato dell’applicazione stessa sono andati persi.Sad smile
Un altro aspetto importante è il fatto che, tra le cause che possono causare il TombStoning di un applicazione puo esserci anche il nostro stesso codice il quale, può ad esempio invocare dei Launchers o Chooser ovvero dei tasks il cui compito è quello di eseguire delle azioni o interagire con l’utente, tra questi, ad esempio, quello che permette all’utente di selezionare una foto tra quelle memorizzate nel device.

Essendo queste, passatemi il termine, “Finestre di dialogo” dei programmi a tutti gli effetti il risultato per la nostra applicazione è esattamente quello di prima, ovvero l’effetto Tombstoning e la perdita delle informazioni di stato non appena un qualsiasi task viene invocato.
Ad esempio, nel nostro caso premedo il tasto Search si ha: l’attivazione del MarketplaceSearchTask, la disattivazione della nostra applicazione e il fatto che, premendo subito il tasto Back dell’emulatore la textbox appare vuota.
Decisamente non piacevole, sopratutto per l’utente finale al quale poco importa di cosa succede alla nostra applicazione.Confused smile

E quindi? Dobbiamo strutturare l’applicazione affinchè, quando deattivata, persista le informazioni necessarie per un suo corretto ripristino durante l’eventuale riattivazione facendo credere all’utente che l’applicazione non sia mai stata interrotta.
Fortunatamente nel framework di Windows Phone abbiamo due classi che ci aiutano in questo: PhoneApplicationService  e PhoneApplicationPage le quali espongono una proprietà State di tipo IDictionary<string,object> che viene salvata/riletta durante la fase di Tombstoning e successiva riattivazione permettendoci quindi di associare a questa sessione le informazioni transienti.

Le guidelines indicano di usare:

  • PhoneApplicationPage per gestire informazioni legate allo stato della pagina.
  • PhoneApplicationService per gestire info legate all’intera applicazione all’interno degli eventi Deactivated/Activated.

All’interno del dictionary esposto dalla proprietà State di entrambe le classi è possibile associare qualsiasi tipo purchè serializzabile.

Aggiungendo nella pagina RunTask il seguente codice:

private const string Key = "SearchText";
 
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
   base.OnNavigatedFrom(e);
   if (this.State.ContainsKey(Key))
   {
      txtSearch.Text = this.State[Key].ToString();
      this.State.Remove(Key);
   }
}
 
protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
   base.OnNavigatedTo(e);
   if (!string.IsNullOrEmpty(txtSearch.Text))
   {
      this.State.Add(Key, txtSearch.Text);
   }
}

andiamo a salvare/leggere il contenuto della textbox col risultato che, in caso di Tombstoning, alla successiva riattivazione la pagina viene riproposta nello stesso stato in cui l’utente l’aveva lasciata il quale sarà convinto che dietro le quinte non sia avvenuto nulla mentre, in realtà, di cose ne sono accadute parecchie Smile.

Ff817008.5e84773d-ae0d-43b8-a956-ffdac77b2922(en-us,VS.92).png

Quando inizierete a pensare alla vostra prossima applicazione Windows Phone 7, ricordatevi quindi che avrete a che fare con un applicazione che potrà nascere e morire parecchie volte e sopratutto, almeno fino a quando le cose non cambieranno, scordatevi di avere a che fare con applicazioni tipicamente stateful.

Il diagramma a fianco descrive in maniera dettagliata I vari stati in cui un applicazione Windows Phone 7 può trovarsi e come vanno gestiti.

 

…cosa ci tocca fare per risparmiare un po’ di batteria…. Just kidding

 

Technorati Tags: ,

author: Corrado Cavalli | posted @ mercoledì 28 luglio 2010 7.35 | Feedback (6)

How to change Windows Phone 7 Startup Page


Quando si crea un nuovo progetto Windows Phone 7 viene automaticamente creata una pagina MainPage.xaml che rappresenta la pagina iniziale dell’applicazione:

image

Nel caso si voglia cambiarla il processo non è esattamente lo stesso di Silverlight, questo perchè la pagina è in realtà ospitata all’interno del Frame di navigazione PhoneApplicationFrame il quale viene impostato come RootVisual allo startup all’interno di App.Xaml.cs

   1: private void InitializePhoneApplication()
   2:   {
   3:      if (phoneApplicationInitialized)
   4:         return;
   5:  
   6:      // Create the frame but don't set it as RootVisual yet; this allows the splash
   7:      // screen to remain active until the application is ready to render.
   8:      RootFrame = new PhoneApplicationFrame();
   9:      RootFrame.Navigated += CompleteInitializePhoneApplication;
  10:  
  11:      // Handle navigation failures
  12:      RootFrame.NavigationFailed += RootFrame_NavigationFailed;
  13:  
  14:      // Ensure we don't initialize again
  15:      phoneApplicationInitialized = true;
  16:   }
  17:  
  18:   // Do not add any additional code to this method
  19:   private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e)
  20:   {
  21:      // Set the root visual to allow the application to render
  22:      if (RootVisual != RootFrame)
  23:         RootVisual = RootFrame;
  24:  
  25:      // Remove this handler since it is no longer needed
  26:      RootFrame.Navigated -= CompleteInitializePhoneApplication;
  27:   }

inoltre al momento non c’è traccia di questa impostazione all’interno delle proprietà del progetto.

La risposta è nel file WMAppManifest.xml, non molto evidente a dire il vero, presente nella cartella Properties del progetto:

image


Aprendolo è possibile trovare l’elemento <defaulTask>

<Tasks>       
  <DefaultTask Name ="_default" NavigationPage="MainPage.xaml"/>
</Tasks>

Sostituendo il contenuto dell’attributo NavigationPage è possibile specificare la nuova starting page. Smile

Technorati Tags: ,

author: Corrado Cavalli | posted @ giovedì 22 luglio 2010 19.03 | Feedback (0)

SILF: Silverlight Install and Logging Framework


Se è vero che la prima impressione è quella che conta, perchè questo non vale per le applicazioni Silverlight?
Alla data di oggi l’adozione mondiale di Silverlight è attorno al 60%, questo significa che il 40% degli utenti che finiscono sulla nostra pagina quello che si ritrovano è un desolante:

image oppure image

che per un utente non esperto potrebbe significare tutto e niente.
Non sarebbe meglio fornire un esperienza più “amichevole” e magari riuscire anche a capire, tra gli utenti che non hanno Silverlight, quanti hanno deciso di installare il plug-in e quanti invece hanno abbandonato la pagina?

image

La buona notizia è che grazie a un framework (in realtà poco pubblicizzato) chiamato SILF (Silverlight Install and Logging Framework) http://mediaevangelism.com/silf/silf.html tutto questo è molto semplice, basta sostituire il file silverlight.js del progetto web col file silf.js (visto che sono quasi 100K è consigliata la compressione)

   1: <script type="text/javascript" src="silf.js"></script>

e  aggiungere nella pagina che ospita il plug-in uno script che inizializza il framework:

   1: <script type="text/javascript">
   2:        SILF.appName = "Test";
   3:        SILF.appVersion = "1.2.3";
   4:        SILF.logEntryflow = true;
   5:        SILF.logInstall = true;
   6:        SILF.loggingURIinstall = "http://mysite.com/public?state=install";  
   7:      SILF.minSlVersion = "3.0.50106.0";
   8:      SILF.SilverlightControlHost = "silverlightControlHost";
   9:      // div which contains Silverlight control 
  10:      // Use this section to configure messages
  11:      SILF.PromptInstall = "Please <a href='#' onclick='SILF.InstallClicked()'>click here to install Silverlight</a>";
  12:      SILF.PromptFinishInstall = "Please wait for Silverlight installation to complete. You may need to refresh the page.";
  13:      SILF.PromptUpgrade = "Please <a href='#' onclick='SILF.UpgradeClicked()'>click here to upgrade Silverlight</a>";
  14:      SILF.PromptFinishUpgrade = "Please wait for Silverlight upgrade to complete. You will need to restart your browser.";
  15:      SILF.PromptRestart = "Please exit/quit and restart your browser to proceed";
  16:      SILF.PromptNotSupported = "Sorry, your browser or operating system are not supported";
  17:      // If you want to redirect on Silverlight not supported, rather than show a slate, enable this variable// 
  18:      SILF.RedirectNotSupported = "http://bing.com";
  19:     
</script>

e nel body, oltre ad aggiungere una chiamata al metodo onLauncherPageLoad nell’evento onLoad, aggiungere la classica definizione del plugin Silverlight.

 
   1: <body onload="SILF.onLauncherPageLoad();">
   2:     <form id="form1" runat="server" style="height:100%">
   3:     <div id="silverlightControlHost">
   4:         <object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
   5:           <param name="source" value="ClientBin/InstallExperience.xap"/>
   6:           <param name="onError" value="onSilverlightError" />
   7:           <param name="background" value="white" />
   8:           <param name="minRuntimeVersion" value="3.0.40818.0" />
   9:           <param name="autoUpgrade" value="true" />          
  10:         </object><iframe id="_sl_historyFrame" style="visibility:hidden;height:0px;width:0px;border:0px"></iframe></div>
  11:     </form>
  12: </body>
Fatto questo se l’utente non ha il plugin installato verrà mostrato ciò che avete definito con la proprietà PromptInstall (ricordate che è possible usare codice HTML) e lo stesso accade per le varie fasi dell’installazione, inoltre l’eventuale uri specificata verrà invocata con una serie di informazioni rigurdanti lo status dell’ installazione.
Al link indicato in precedenza trovate la descrizione delle varie proprietà e come vanno usate (provate a visitare la pagina col plugin Silverlight disabilitato), segnalo solo che il file silf.js è un po’ datato quindi vi consiglio di aggiornare l’elenco delle versioni di Silverlight identificate in questo modo:
 
   1: var slVers = new Array(
   2:          "4.0.50420.0", // 4 GDR2
   3:          "4.0.50401.0", // 4 RTM
   4:             "4.0.50303.0",    // 4 RC
   5:             "4.0.41108.0",  // 4 Beta 1 
   6:             "3.0.50106.0",  // 3 GDR 3
   7:             "3.0.40818.0",  // 3 GDR 2
   8:             "3.0.40723.0",  // 3 GDR 1
   9:             "3.0.40624.0",    // 3 RTW
  10:             "3.0.40307.0",
  11:             "2.0.40115.0",
  12:             "2.0.31005.0",
  13:             "2.0.30523.9",
  14:             "2.0.30523.8",
  15:             "2.0.30523.6",
  16:             "2.0.30226.2",
  17:             "1.0.30715.0",
  18:             "1.0.30401.0",
  19:             "1.0.30109.0",
  20:             "1.0.21115.0",
  21:             "1.1.20926.0",
  22:             "1.0.20816"
  23:             );

Enjoy…

Technorati Tags: ,

author: Corrado Cavalli | posted @ mercoledì 7 luglio 2010 21.56 | Feedback (2)

IIS Express


Nel blog di ScottGu è da poco apparso un post decisamente interessante: A breve, oltre a Cassini e la versione “full” di IIS sarà disponibile una versione “Express” feature complete che diventerà il web server ufficiale nelle prossime versioni di Visual Studio.

Tutti i dettagli qui: http://weblogs.asp.net/scottgu/archive/2010/06/28/introducing-iis-express.aspx

Technorati Tags:

author: Corrado Cavalli | posted @ martedì 29 giugno 2010 9.05 | Feedback (0)

RIA Services vNext Feedback


Wcf-ria-forum-logoCosì com’è successo per Silverlight e WPF il team dei WCF RIA Services sta raccogliendo feedback per capire quali sono le le features da implementare nella prossima versione. Volete dire la vostra? allora partecipate a questa survey: http://dotnet.uservoice.com/forums/57026-wcf-ria-services

 

Technorati Tags:

author: Corrado Cavalli | posted @ sabato 15 maggio 2010 7.23 | Feedback (0)