Technology Experience
Senza categoria

Silverlight 4 e la possibilità di navigare su Page definite in un assembly separato

Introduzione
Sappiamo tutti che Silverlight 4 ha un meccanismo di navigation interno. A cosa serve? Il tutto si basa sul controllo Frame, che può contenere oggetti Page. Questi oggetti Page possono contenere a loro volta contenere tutto ciò che vi può passare per la testa, quindi testo, immagini, altri controlli, animazioni, etc. etc.

Perchè si chiama navigation? Perchè dietro le quinte Silverlight fa un pochino di cose interessanti, prima fra tutte la history delle Page che avete visitato. Attraverso l’oggetto NavigationService, quindi, potete chiamare metodo come GoBack(), GoForward(), accedendo quindi a tutte le Page già visitate dall’utente.

Maggiori informazioni sull’argomento a questo indirizzo.

Concetti base
Ok, supponiamo di aver creato una semplice SilverlightApplication1, hostata da un progetto SilverlightApplication1.Web. Sulla MainPage.xaml creiamo un controllo Frame:

<UserControl x:Class="SilverlightApplication1.MainPage"
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 xmlns:nav="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
 mc:Ignorable="d"
 d:DesignHeight="300" d:DesignWidth="400">
 <nav:Frame Background="LightCyan" Source="/Page1.xaml">
 </nav:Frame>
</UserControl>

 

Il controllo Frame è definito nell’assembly System.Windows.Controls.Navigation, quindi ho dovuto dichiarare il namespace ‘nav’. Nulla di anormale fin qua.

Notare la proprietà Source del controllo, impostata su “/Page1.xaml”. Questo significa che nella stessa directory dove abbiamo la MainPage.xaml dobbiamo aggiungere una Silverlight Page, chiamarla Page1.xaml, e definirne il contenuto. Supponiamo di aver creato una pagina così:

<navigation:Page x:Class="SilverlightApplication1.Page1" 
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 mc:Ignorable="d"
 xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
 d:DesignWidth="640" d:DesignHeight="480"
 Title="Page1 Page">
 <TextBlock Text="Page 1" FontSize="56" />
</navigation:Page>

 

La pagina contiene una semplice TextBlock con scritto “Page 1”. In questo momento, quindi, se avviate il progetto la prima cosa che vedete è:

NavigationPage1

Impostazione della proprietà UriMapper del Frame
Ritorniamo sul valore della proprietà Source del Frame. In questo momento, esso rappresenta a tutti gli effetti il path fisico del file .xaml che vogliamo caricare e renderizzare. E’ possibile però "giocare” con la proprietà UriMapper del Frame, in modo tale da “convertire” un url logico in uno fisico. Supponiamo di impostarla come segue:

<nav:Frame Background="LightCyan" Source="/Page1">
 <nav:Frame.UriMapper>
 <uriMapper:UriMapper>
 <uriMapper:UriMapping Uri="/{pageName}" MappedUri="/{pageName}.xaml" />
 </uriMapper:UriMapper>
 </nav:Frame.UriMapper>
</nav:Frame>

 

Notare l’import del namespace uriMapper, definito come segue:

xmlns:uriMapper="clr-namespace:System.Windows.Navigation;assembly=System.Windows.Controls.Navigation"

 

Cosa succede adesso? Succede che Source adesso vale “/Page1”, e ci pensa l’UriMapper a convertirlo nel vero Uri che punta al file .xaml. Tutte le volte che chiediamo una pagina nella forma “/PaginaElencoOrdini”, l’uri effettivo diventerà “/PaginaElencoOrdini.xaml”. Ovviamente possiamo sfruttare questa caratteristica in modo più intelligente, per esempio mettendo tutti i files di Page in una cartella e lasciare che l’UriMapper li recuperi per noi. Maggiori informazioni a questo indirizzo.

Ed ora la parte più “difficile”: navigare su pagine definite in un assembly esterno
Lo so, sono blog-orroico: questo è il tema principale di questo post, e ci sono arrivato solo alla fine. Supponiamo di voler aggiungere un nuovo progetto – SilverlightClassLibrary1.Pages – contenente solo oggetti di tipo Page. Vogliamo navigare su queste pagine, e raggiungerle attraverso il controllo Frame.

La vera domanda è questa: quale url devo utilizzare? Qual’è l’url corretto che punta ad un file Page1.xaml definito nell’assembly SilverlightClassLibrary1.Pages?

La risposta, una volta trovata la soluzione, è abbastanza semplice. E’ bastato trovare la pagina Pack URIs in WPF. Definiamo il controllo Frame come segue:

<nav:Frame Background="LightCyan" Source="/Page1">
 <nav:Frame.UriMapper>
 <uriMapper:UriMapper>
 <uriMapper:UriMapping Uri="/External/{pageName}"
 MappedUri="/SilverlightClassLibrary1.Pages;component/{pageName}.xaml" />
 <uriMapper:UriMapping Uri="/{pageName}" MappedUri="/{pageName}.xaml" />
 </uriMapper:UriMapper>
 </nav:Frame.UriMapper>
</nav:Frame>

 

Abbiamo aggiunto un UriMapping nuovo. Se la pagina viene richiesta nella forma “/External/{pageName}”, il Mapped Uri viene risolto così:

/SilverlightClassLibrary1.Pages;component/{pageName}.xaml

 

Quello che dobbiamo fare poi è aggiungere il riferimento a SilverlightClassLibrary1.Pages nel progetto SilverlightApplication1. Fatto questo, abbiamo terminato.

In pratica, la pagina viene cercata nell’assembly SilverlightClassLibrary1.Pages. Adesso basta reimpostare il Source su “/External/Page1” per caricare la pagina dall’altro assembly. Ovviamente prima di eseguire dobbiamo andare nell’altro assembly e definire anche lì una Page1.xaml – magari con un contenuto diverso rispetto a quella precedente – per ottenere quanto segue:

NavigationPage2

Missione compiuta!

Il codice sorgente, se proprio volete vederlo – è scaricabile da qui (86 Kb).

Send to Kindle

Igor Damiani

La sua passione per l'informatica nasce nella prima metà degli anni '80, quando suo padre acquistò un Texas Instruments TI-99. Da allora ha continuato a seguire l'evoluzione sia hardware che software avvenuta nel corso degli anni. E' un utente, un videogiocatore ed uno sviluppatore software a tempo pieno. Igor ha lavorato e lavora anche oggi con le più moderne tecnologie Microsoft per lo sviluppo di applicazioni: .NET Framework, XAML, Universal Windows Platform, su diverse piattaforme, tra cui spiccano Windows 10 piattaforme mobile. Numerose sono le app che Igor ha creato e pubblicato sul marketplace sotto il nome VivendoByte, suo personale marchio di fabbrica. Adora mantenere i contatti attraverso Twitter e soprattutto attraverso gli eventi delle community .NET.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.