Solución original : Añadir un DependencyProperty propio a un control

IC210095

Trabajando con Windows Phone 8 y concretamente con el control de mapas y el Toolkit de Windows Phone, que por cierto ahora es distinto que con Windows Phone 7 y 7.5, me he encontrado con el problema de que al momento de colocar Pushpins de forma dinámica usando una lista la propiedad ItemsSource de MapItemsControl no es Bindable.

Ante este problema una solución es asignar la lista directamente por código y con eso acabamos. Solución rápida y simple.

Pero si buscamos ser coherentes con lo que es o son las aplicaciones WPF de separar lo que es la lógica de la interfaz de usuario (XAML) y que por eso existe el patrón MVVM esta solución no es pura 🙂

Encontré una solución original que no solo sirve en este caso sino que también en cualquier otro. Crear tu propio propiedad Bindable y asignarlo a cualquier control como si fuera nativo.

El enlace lo encontráis al final de este post pero yo os lo cuento un poco por encima.

Si creas una clase estática con un Dependency Property luego puedes usar esa propiedad (que también debes hacerla estática) en cualquier control WPF. El truco está en programar el método que se debe ejecutar cuando cambia la propiedad Dependecy Property.

Aquí tienes la sintaxis del MSDN:


public static DependencyProperty Register(
string name,
Type propertyType,
Type ownerType,
PropertyMetadata typeMetadata,
ValidateValueCallback validateValueCallback
)

De esta forma puedes conseguir leer las propiedades del control al cual te “hospedas” y asignar valores en código.


private static void OnPushPinPropertyChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
UIElement uie = (UIElement)d;
var pushpin = MapExtensions.GetChildren((Map)uie).OfType<MapItemsControl>().FirstOrDefault();
pushpin.ItemsSource = (IEnumerable)e.NewValue;
}

 

Aquí tenéis el ejemplo completo: MVVM Windows Phone 8 – adding a collection of pushpins to a map

Si teneis alguna duda me lo preguntáis.

Millorar ObservableCollection

A StackOverflow s’ha publicat un exemple de com es pot fer un ObservableCollection més efectiu.

ObservableCollection és una llista genèrica que implementa INotifyPropertyChanged i per tant avisa a la UI dels canvis que hi ha dins la llista. Bàsicament si s’afegeix o es borra algun element.

El problema és que no és Thread safe ni tampoc Thread Affinity. Per tant, quan un Thread que no és l’UI actualitza aquesta llista es genera una excepció.

El segon, és que per cada operació d’afegir o borrar es llencen els events corresponent per notificar a UI del canvi sense l’opció de poder-los agrupar i que només es faci una vegada la notificació després d’un conjunt d’operacions.

Consulteu l’exemple que és força interessant.

Fast performing and thread safe observable collection

 

 

Mouse events Grid Control

In this article is explained How to handle mouse event on entire Grid Control in WPF or Windows Store apps or Windows Phone apps.
It is really simple and I would not write anything about that in my blog if I had not had problems with this simple action in my Windows Phone project that I am working.
At the bottom of this article it says the gold rule:
In order for this to work you need to always set the Grid Background, either to transparent or to whatever you like, because if its null the event isn’t triggered…

And that’s true, remember to put a background on your Grid, by default could be set to null.

Windows Phone : TextBlock justify doesn’t work

TextBlockImg3

TextBlock is the control to used for writing text on the screen. It is really simple and easy. But, I don’t know why, justify the text using the TextAlignment attribute doesn’t work.

Luckily we have the RichTextBox control.

 

<RichTextBox TextAlignment=”Justify” IsReadOnly=”True”>
<Paragraph>
Put your text here
</Paragraph>
</RichTextBox>

 

Happy coding.

Blend 2012 and weird error

Blend2012

Last week, using Blend 2012 in a Windows Phone 8 Project caused a weird error. An error hard to know why it is happening and which sentence is the guilty.

The error says:

“Unable to cast object of type ‘System.Reflection.CustomAttributeData’ to type ‘System.ComponentModel.TypeConverterAttribute’

If you search on the Internet about this error you can find some webs talking about Update 2 of Visual Studio 2012 in WP8 projects but in my case the problema came from another spot.

I was working with DataTrigger and ChangePropertyAction in Windows Phone 8 using Blend 2012. From properties tab I put the Binding, the Value to compare, the property to modify and finally the value to assign.

In this case the property was Source from Image Control and Blend 2012 write in XAML this piece of code as follows:

<ec:DataTrigger Binding=”{Binding Path=Level}” Value=”Level1″>
<ec:ChangePropertyAction PropertyName=”Source”>
<ec:ChangePropertyAction.Value>
<Source>/Assets/Levels/logoGraduacio1stars.png”</Source>
</ec:ChangePropertyAction.Value>
</ec:ChangePropertyAction>
</ec:DataTrigger>

The famous error is below this line:

<Source>/Assets/Levels/logoGraduacio1stars.png”</Source>

 

The correct piece of code has to be:

<ec:DataTrigger Binding=”{Binding Path=Level}” Value=”Level1″>
<ec:ChangePropertyAction PropertyName=”Source”>
<ec:ChangePropertyAction.Value>
<BitmapImage UriSource=”/Assets/Levels/logoGraduacio1stars.png”></BitmapImage>
</ec:ChangePropertyAction.Value>
</ec:ChangePropertyAction>
</ec:DataTrigger>

Enjoy programming.

 

Threading Considerations for Binding and Change Notification in XAML

I read a very similar article about how to work with MVVM and multithreading aspects. The problem is well known; in XAML’s Binding features, if you want to communicate any change to UI through Binding object, you need to implement INotifyPropertyChanged on model class, this interface has an event named PropertyChanged that is needed to update the UI, however in multithreading scenarios, you could have secondary threads modifying the model and this implies that the PropertyChanged event will be caught on a secondary thread and then you will the following exception:

Threads other than the UI thread are not allowed to access or manipulate UI objects

In this article you can read how to solve the problem in Silverlight (for WPF and WP as well) but it is not suitable for Portable Library scenarios. In Portable Library we have neither the Deployment class or even the Dispatcher class, so we have to take the SynchronizationContext class.

Implementation is really easy, you need to declare a global class field as follows

private SynchronizationContext _context = SynchronizationContext.Current;

Now, you have in _context the thread which created the class, you need to ensure that this is the same as controls’ thread: Thread UI

The next step is :


protected virtual void OnPropertyChanged(string propertyName)

{

PropertyChangedEventHandler handler = this.PropertyChanged;

if (handler != null)

{

var e = new PropertyChangedEventArgs(propertyName);

if (SynchronizationContext.Current == _context)

{

handler(this, e);

}

else

{

_context.Post(obj =>

{

handler(this, e);

}, null);

}

}

}

_context.Post is called only if the current thread is not the same as the creator thread.

System.Runtime error en WP8 y librerías portables

Un caso raro es cuando usamos librerías portables y Microsoft.Bcl no da un error de compilación System.Runtime. En un primer momento no tenemos muy claro de que se trata y tampoco nos da ninguna pista de que puede ser.

Después de buscar y buscar resulta ser un bug de NuGet en que te pone una redirección en el archivo app.config

 

<dependentAssembly>

<assemblyIdentity name=”System.Runtime” publicKeyToken=”b03f5f7f11d50a3a” culture=”neutral” />

        <bindingRedirect oldVersion=”0.0.0.0-2.6.3.0″ newVersion=”2.6.3.0″ />

</dependentAssembly>

 

De modo que debes eliminar esa línea para que todo funcione correctamente otra vez.

<dependentAssembly>

<assemblyIdentity name=”System.Runtime” publicKeyToken=”b03f5f7f11d50a3a” culture=”neutral” />

</dependentAssembly>

Llibreries portables i Thread UI

Amb .NET 4 apareixen les llibreries portables que penso que són fantàstiques per poder fer una programació completament reutilitzable en les diferents tecnologies que tenim disponibles amb Microsoft .NET : Windows Apps, Windows 8 Store, Windows Phone i Silverlight.

Hem de saber però que aquest tipus de llibreries utilitzen un subconjunt de les característiques que poden tenir en comú les diferents tecnologies i abans de posar-nos a fer res hem de consultar quines funcionalitats ens permeten fer les llibreries portables.

Hi ha un aspecte que sempre ens trobem que és com fem referència al Thread UI de l’aplicació. El Dispatcher no el podem fer servir des de les llibreries portables. Tenim la clase SynchronizationContext per fer-ho.

De fet, l’ús és molt senzill, declarem una variable a nivell de classe com aquesta

#región Fields

private SynchronizationContext _context = SynchronizationContext.Current;

#endregion

 

I llavors sempre que vulguem assegurar-nos que una funció s’executi al mateix thread que ha creat la classe llavors:

if (SynchronizationContext.Current == _context)

{

/*Do something */

}

else

{

/*El thread actual no és el mateix */

_context.Post(obj =>

{

/*Do something */

},null);

}

Fixa’t que el que mira és si el thread actual és el mateix que ha creat la classe, per tant l’únic que ens hem de preocupar és que el Thread UI creí la classe.
Més informació:

Portable Class Library and ObservableCollection, updating UI Thread

Portable class library equivalent of Dispatcher.Invoke or Dispatcher.RunAsync

 

 

 

ObservableCollection en entornos multi threading

En WPF puedes usar la lista ObservableCollection para poder hacer enlace con controles tipo lista, de esta forma, usando únicamente XAML puedes enlazar una propiedad de este tipo a un control.

ObservableCollection tiene la característica de que en cuando se añade un elemento o se borra o se modifica se notifica al control XAML para que se actualice. Dicho de otra forma, implementa el INotifyPropertyChanged.

La implementación es simple y sencilla pero puede ser un problema en entornos multi-threading porque el mismo thread que crea el control XAML debe ser el mismo que actualiza la lista del tipo en cuestión.

Los entornos multi-threading esto no es siempre posible i sobretodo en implementaciones con el MVVM. Puedes usar distintas técnicas para solucionarlo, lo único que necesitas es que Dispatcher se encargue de actualizar dicha lista.

Pero he encontrado una solución original, la he probado y funciona muy bien.

Dejo el enlace aquí para que puedas consultar:

Fast performing and thread safe observable colección

Para más información:

Threading Considerations for Binding and Change Notification in Silverlight 5

 

 

 

 

Navegación a paginas XAML de otros ensamblados

Tanto en WPF como en Silverlight como en Windows Phone trabajamos con ventanas escritas en XAML que son XML que definen la interface de usuario.

Puede ser muy habitual tener definidas estas ventanas en otros ensamblados, como por ejemplo librerías, y en el momento de querer navegar hasta esta ventana tenemos la duda de como se puede hacer ya que el servicio de navegación en WPF funciona con Uri.

Así que, cual es la Uri de una ventana definida en otro ensamblado?

/{assemblyName};component/{pathToResource}

Como por ejemplo : “/SharedPages;component/TestPage.xaml” donde SharedPages es el nombre del ensamblado y /TestPage.xaml la ruta a partir de la raíz del proyecto para encontrar la ventana.