Ottenere la posizione assoluta di un controllo in WinRT

Prima o poi avrete bisogno di ottenere la posizione assoluta di un controllo in WinRT. Potete fare in questo modo:

// Obtain transform information based off root element
GeneralTransform gt = this.TransformToVisual(Window.Current.Content);

// Find the four corners of the element
Point topLeft = gt.TransformPoint(new Point(0, 0));
Point topRight = gt.TransformPoint(new Point(this.RenderSize.Width, 0));
Point bottomLeft = gt.TransformPoint(new Point(0, this.RenderSize.Height));
Point bottomRight = gt.TransformPoint(new Point(this.RenderSize.Width, this.RenderSize.Height));

basato su how-to-get-the-position-of-a-control-in-silverlight

Annunci

How to get the absolute position of a control in WinRT

Sooner or later you will need to find the absolute position of a control in WinRT.
Here is how you can achieve it:

// Obtain transform information based off root element
GeneralTransform gt = this.TransformToVisual(Window.Current.Content);

// Find the four corners of the element
Point topLeft = gt.TransformPoint(new Point(0, 0));
Point topRight = gt.TransformPoint(new Point(this.RenderSize.Width, 0));
Point bottomLeft = gt.TransformPoint(new Point(0, this.RenderSize.Height));
Point bottomRight = gt.TransformPoint(new Point(this.RenderSize.Width, this.RenderSize.Height));

based on how-to-get-the-position-of-a-control-in-silverlight

Binding for Dummies (ep. 3)

Nei primi due episodi di Binding for Dummies (ep. 1 ed ep. 2) abbiamo visto cosa è il binding, come implementarlo e come far si che le modifiche al nostro modello ad oggetti vengano riportate in modo automatico all’interfaccia grafica tramite l’implementazione dell’interfaccia INotifyPropertyChanged.

Passiamo ora a vedere come implementare il binding quando si tratta di collezioni di oggetti. Se fino ad ora questo approccio non vi ha convinto (perché in effetti aumenta il livello di complicazione generale) da adesso non potrete più farne a meno.

Ipotizziamo di avere una lista di oggetti da visualizzare nella UI. Senza il binding avreste dovuto aggiungere n ListBoxItem e valorizzarli da XAML uno per uno. Ma in questo modo dovreste conoscere in anticipo il numero di elementi della lista. Inoltre dovreste replicare il layout di ogni singolo elemento (immaginate ad un elemento complesso che abbia una immagine, un titolo e una descrizione) e scrivere due volte lo stesso codice è sempre un errore. Oppure avreste potuto dare un nome ad ogni elemento della lista (ogni immagine, ogni titolo, ecc.) e valorizzarli dal code behind all’interno di un ciclo for each della vostra lista. Oppure da codice avreste potuto, per ogni elemento della vostra lista, creare un ListBoxItem con tutte le sue proprietà (immagine, testo, ecc.) ed aggiungerlo alla ListBox. Non vedremo nessuna di queste cose perché portano via davvero molto tempo, ma potreste esercitarvi con tutte queste ipotesi perché si impara sempre qualcosa.

Invece vediamo direttamente come il binding si preoccupi di tutto. Tutto quello che dovete fare è creare la vostra lista, indicarla come ItemSource della ListBox ed infine definire il template del singolo elemento. Vediamo come, partendo da un semplice caso.

Creiamo una lista di stringhe nel nostro modello ad oggetti
public List<string> lista {get; set;}
Nel costruttore della classe stanziamo la lista e riempiamola di tre elementi
public Data ()
{
this.lista = new List<string> { “elemento 1”, “elemento 2”, “elemento 3” };
}
Il DataSource del contenitore padre (in questo caso ContentPanel) deve essere già bindato al nostro modello ad oggetti
ContentPanel.DataContext = data;
A questo punto nello XAML della ListBox valorizziamo la proprietà ItemsSource, che indica la sorgente degli elementi della ListBox
<ListBox ItemsSource=”{Binding lista}”>
La ListBox creerà automaticamente un ListBoxItem per ogni elemento della nostra lista ed ognuno di questi elementi avrà il layout indicato dalla proprietà DataTemplate dell’ItemTemplate in questo modo
<ListBox ItemsSource=”{Binding lista}”>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text=”{Binding}”/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
In questo caso il Template è molto semplice e nel binding non viene indicato nessun campo perché è tutto l’oggetto stringa ad essere bindato al Text della TextBlock.

E se avessimo una lista di oggetti custom? Creiamo una classe CustomObject
class CustomObject
{
public string Name { get; set; }
public string Description { get; set; }
public string Colore { get; set; }
public int Numero { get; set; }
}
e riempiamola nel costruttore
this.listaOggetti = new List<CustomObject>
{
new CustomObject{Name = “Nome 1”, Colore= “red”, Description = “kjsahdfasbhdfòlahòs”, Numero = 1},
new CustomObject{Name = “Nome 2”, Colore= “blue”, Description = “kjsahdfasbhdfòlahòs”, Numero = 2},
new CustomObject{Name = “Nome 3”, Colore= “green”, Description = “kjsahdfasbhdfòlahòs”, Numero = 3},
new CustomObject{Name = “Nome 4”, Colore= “orange”, Description = “kjsahdfasbhdfòlahòs”, Numero = 4},
new CustomObject{Name = “Nome 5”, Colore= “yellow”, Description = “kjsahdfasbhdfòlahòs”, Numero = 5}
            };
Possiamo a questo punto decidere cosa bindare alla TextBlock dell’ItemTemplate, per esempio Name
<ListBox ItemsSource=”{Binding listaOggetti}”>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text=”{Binding Name}”/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

Oppure possiamo creare un template più complesso
<ListBox ItemsSource=”{Binding listaOggetti}”>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation=”Horizontal”>
<Rectangle Height=”50″ Width=”100″ Fill=”{Binding Colore}” />
<StackPanel>
<TextBlock Text=”{Binding Name}” FontSize=”24″/>
<TextBlock Text=”{Binding Description}” FontSize=”18″/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
dove abbiamo bindato non solo le proprietà del testo, ma anche il colore. Potete mettere i binding tutte le proprietà dei vostri oggetti grafici, ed adattarli al vostro contenuto. E potete selezionare quali proprietà dei vostri oggetti custom mettere in binding.

Ma soprattutto potete cambiare l’interfaccia in modo semplice oppure definire due interfacce diverse da mostrare in alternativa (una vista con molti dettagli e una vista con solo i thumbnails per esempio).

Come al solito, trovate il codice di questo episodio qui http://1drv.ms/1hk5jE9.

Nel prossimo episodio vedremo che esiste una lista particolare (ObservableCollection) che implementa l’interfaccia INotifyPropertyChanged e che permette di riflettere i cambiamenti del vostro modello ad oggetti anche operando sulle liste.

Binding for Dummies (ep.2)

Nel primo episodio di Binding for Dummies abbiamo visto come implementare il data binding in un caso semplice, caso che però non rende chiari i vantaggi di questo approccio ma fa sembrare solo di introdurre inutili complicazioni.

In questa seconda parte vedremo invece come i vantaggi del data binding diventino evidenti nel momento in cui permettono di aggiornare l’interfaccia grafica al variare del nostro modello ad oggetti senza dover scrivere alcun codice aggiuntivo per gestire queste variazioni.

Per prima cosa capiamo bene di cosa stiamo parlando.
Inseriamo un bottone nella nostra pagina xaml, così
<Button  Content=”Premi qui”/>

Associamo ora una funzione all’evento click del bottone. Il codice xaml finale sarà:
<Button Content=”Premi qui” Click=”Button_Click” />
Potete ottenere questo semplicemente digitando all’interno del tag Button il comando Click= e lasciare all’intellisense creare la funzione per voi,
image
oppure selezionare il bottone e fare doppio click nella casella di testo associata all’evento click nella finestra proprietà (dove ora c’è scritto Button_Click); anche questa seconda modalità creerà per voi la funzione agganciata all’evento click del bottone
image

Troverete nel file di code-behind la funzione Button_Click appena creata, all’interno della quale andremo a scrivere la logica che vogliamo sia eseguita al click del pulsante.

Prima di scrivere il codice della funzione dobbiamo però spostare la creazione dell’oggetto data al di fuori del costruttore della mainpage, altrimenti l’oggetto non sarà visibile al di fuori di quella funzione. Spostiamo dunque
//Creazione dell’oggetto data
Data data = new Data();
prima della definizione del costruttore. A questo punto possiamo scrivere dentro Button_Click il codice che modificherà il valore della proprietà etichetta
private void Button_Click(object sender, RoutedEventArgs e)
{
data.Etichetta = “Hai premuto il pulsante”;
}
Se provate ad implementare questo codice, osserverete che alla pressione del pulsante, quello che succede è … NIENTE
La vostra variabile ha cambiato valore, ma questo cambiamento non si riflette nell’interfaccia. Per ottenere questo dobbiamo modificare la nostra classe Data.

Per prima cosa dobbiamo implementare l’interfaccia INotifyPropertyChanged. Aggiungete alle direttive using della classe
using System.ComponentModel;
modificate la definizione della classe in questo modo
class Data : INotifyPropertyChanged
aggiungete un evento ed una funzione che lo invochi al cambiare del valore delle proprietà
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(String propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (null != handler)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
L’ultima cosa che dobbiamo fare è andare a modificare l’implementazione della proprietà Etichetta implementando la chiamata alla funzione NotifyPropertyChanged
private string etichetta;
public string Etichetta
{
get
{
return etichetta;
}
set
{
if (value != etichetta)
{
etichetta = value;
NotifyPropertyChanged(“Etichetta”);
}
}
}
Quello che succede ora è che la proprietà pubblica Etichetta non è più implementata automaticamente, ma va esplicitamente a leggere/scrivere il valore del campo privato etichetta. Nel caso in cui il nuovo valore sia diverso dal precedente allora invoca l’evento NotifyPropertyChanged passandogli il parametro “Etichetta” che volendo potete intercettare per capire quale campo è cambiato.
Il fatto che il meccanismo del data binding capisca l’interfaccia INotifyPropertyChanged vi permette di cambiare la UI auomaticamente al cambio dei valori del vostro modello. Premendo il pulsante avete la vostra etichetta cambia la proprietà Text.
Quindi il binding non solo assegna dei valori presi dal modello ai vostri controlli nella UI, ma li lega al modello ed aggiorna la UI ogni volta che il modello cambia. Una volta stabilito questo legame, potete quindi dimenticarvi della UI e pensare solo alla logica del vostro codice.

NOTA: il parametro passato alla funzione NotifyPropertyChanged deve essere il nome della proprietà pubblica, altrimenti il  trucco non funziona.

Trovate il codice completo di questo episodio qui http://1drv.ms/1i4gQ6d

Nel prossimo episodio parleremo di collection di oggetti e scopriremo gli ulteriori vantaggi del binding.

Binding for Dummies (ep. 1)

Il binding è quel processo che permette di legare le proprietà degli elementi della UI alle proprietà delle classi definite nel vostro codice. Una volta imparato ad usare il binding, non ne potrete più fare a meno. Partiamo con un semplice esempio.
Creando un nuovo progetto troverete nella vostra solution un file MainPage.xaml che rappresenta l’interfaccia grafica (UI) della vostra pagina principale, a cui è legato un secondo file MainPage.xaml.cs, detto file di code-behind, che contiene la logica di programmazione della stessa pagina.
Creiamo una semplice TextBlock. All’interno dello XAML della pagina scriverete dunque:
<TextBlock />
Per assegnare il valore della TextBlock potete modificare lo XAML così:
<TextBlock Text=”Hello World” />
Oppure, per modificare questo valore da codice (dalla pagina di code-behind), avete prima bisogno di assegnare un nome al controllo TextBlock nello XAML
<TextBlock x:Name=”Etichetta” />
e a questo punto potete assegnare il valore della proprietà Text all’elemento Etichetta in modo analogo a quanto avete fatto prima direttamente nello XAML
Etichetta.Text = “Hello World”;
In questo modo potete modificare qualsiasi proprietà dei vostri controlli da codice, e quindi cambiarne il valore a seguito di un evento (la pressione di un bottone, ecc.).

Lo svantaggio di questo approccio è che dovrete identificare tutti i vostri controlli nel codice, che non sarà più indipendente dall’interfaccia. Cambiando l’interfaccia avrete dunque bisogno di modificare anche il vostro codice, rendendo di fatto l’applicazione più difficilmente manutenibile.

E’ qui che entra in azione il binding. Il binding vi permette di legare alcune proprietà dell’interfaccia grafica al vostro modello ad oggetti, rendendo il codice perfettamente indipendente dalla UI.

Torniamo al nostro Hello World. Definiamo una classe Data all’interno della nostra applicazione.  Andate su Esplora Soluzioni, cliccate col tasto destro sul progetto e scegliete la voce Aggiungi->Classe. Chiamate il file Data.cs e Visual Studio creerà per voi una classe Data all’interno del file.
class Data
{
}
A questo punto definite una proprietà pubblica di tipo stringa e chiamatela Etichetta all’interno della classe in questo modo:
public string Etichetta { get; set; }
ATTENZIONE: E’ necessario definire le proprietà tramite le funzioni di accesso get e set, altrimenti il binding non funziona (sia implementate in maniera automatica come ho fatto io, sia con la definizione della proprietà privata e delle funzioni get e set).

Terminata la definizione del modello ad oggetti della nostra applicazione, dobbiamo instanziare un oggetto della nostra classe per associarne i valori delle proprietà alla UI.
//Data Binding
//Creazione dell’oggetto data
Data data = new Data();
//Assegnazione della proprietà etichetta
data.Etichetta = “Hello Binding”;

Il primo passo del Binding consiste nell’assegnare un valore alla proprietà DataContext di un oggetto (in questo caso l’oggetto LayoutRoot è la griglia che contiene tutti i controlli della pagina)
//Binding di data all’oggetto LayoutRoot
LayoutRoot.DataContext = data;

NOTA: Tutti gli oggetti della UI contenuti nella grid LayoutRoot faranno riferimento per il binding a questo oggetto se non diversamente specificato.

Il passo finale per assegnare la proprietà alla nostra TextBlock è quello di assegnare dallo XAML alla proprietà Text il valore dell’etichetta tramite il Binding.
<TextBlock  Text=”{Binding Etichetta}”/>

Abbiamo dunque spostato tutta la logica nel modello ad oggetti e tolto ogni riferimento alla UI dal codice. Il legame tra il codice e l’interfaccia grafica è tutto definito nello XAML, e se rendete più complesso il vostro modello ad oggetti (aggiungendo un campo nome e cognome ad esempio) potete aggiungere altri elementi di UI che abbiano delle proprietà in binding con il vostro modello.

Anche se da questo semplice esempio potrebbe risultare più complicato procedere in questo modo, vedremo presto come, aumentando la complessità del modello ad oggetti , la nostra app sarà molto più semplice da gestire. Vedremo nelle prossime puntate come far si che modificando il valore dei campi della nostra classe questi cambiamenti possano essere  automaticamente trasportati nella UI senza scrivere nessun codice aggiuntivo, come usare il binding con collezioni di oggetti e come usare i convertitori per modificare qualsiasi aspetto dell’interfaccia in base al valore del nostro modello.

Trovate tutto il codice di questo esempio a questo link http://1drv.ms/1i2BWBP

Binding for Dummies (ep.2)