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.

Anuncis

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>