Archive

Archive for the ‘Silverlight 5’ Category

[SL5] : Silverlight 5 Toolkit – September 2011

Une version du Silverlight Toolkit vient de sortir spécialement pour Silverlight 5 apportant pas mal de nouveautés au niveau de la gestion des éléments 3D.

  1. Seamless integration of 3D models and other assets with the Content Pipeline
  2. New Visual Studio templates for creating:
    1. Silverlight 3D Application
    2. Silverlight 3D Library
    3. Silverlight Effect
  3. New samples to demo these features

Pour la télécharger rendez-vous ici : http://silverlight.codeplex.com/releases/view/74436

Plus d’informations ici : http://blogs.msdn.com/b/eternalcoding/archive/2011/10/04/silverlight-toolkit-september-2011-for-silverlight-5-what-s-new.aspx

Bon tests 🙂

Publicités
Catégories :Silverlight 5

[SL5] : Sortie de Silverlight 5 RC

Vous pouvez dès à présent télécharger la version RC de Silverlight 5 !

http://www.silverlight.net/learn/overview/what%27s-new-in-silverlight-5

Voici les liens utiles pour utiliser cette RC:

A programme les nouveautés suivantes :

  •      Support du P/Invoke pour appeler des méthodes natives
  •      Le support du 64 bits !
  •      Impression post script
  •      Contrôle à distance dans les médias
  •      Trusted App dans le navigateur possible et non plus uniquement en OOB
  •      PivotViewer inclut dans le plugin

Attention toutefois ceci n’est pas une version GoLive et il est donc possible que des changements soient réalisés d’ici à la sortie définitive. Ne l’utilisez pas dans un environnement de production, mais uniquement dans le but de vous faire la main et de tester d’éventuelles migrations.

Bon tests 🙂

Catégories :Silverlight, Silverlight 5

[SL5] : Silverlight WPF’s {x:Static} MarkupExtension

Silverlight 5 Beta fournit à présent la classe de base MarkupExtension qui lorsqu’on implémente la méthode ProvideValue(IServiceProvider), permet de définir une MarkupExtension customisée, qui peut être interprétée par le parseur de XAML de Silverlight 5.

Ceci permet de réaliser des tâches qui n’étaient pas possible, plutot complexes ou verbeuse à mettre en place. Par exemple il est à présent possible de réaliser un comportement similaire à ce que l’on connait en WPF tel que {x:Type}, {x:Static}, etc.

Dans ce post nous allons voir comment réaliser l’équivalent de x:Static connu en WPF utilisé dans certains cas comme le référencement de constantes dans le XAML. Les adeptes de PRISM l’utilisent généralement pour nommer les régions suivant des constantes définies dans l’infrastructure du projet.

Généralités

Pour faire une MarkupExtension vous devez implémenter une classe dérivant de l’interface IMarkupExtension<T> ou la classe de base MarkupExtension.


    public class YourMarkupExtension: IMarkupExtension<Object>
    {
        public Object ProvideValue(IServiceProvider serviceProvider)
        {
                throw new NotImplementedException();
        }
    }

Implémentation du comportement de {x:Static}


using System;
using System.Windows.Markup;
using System.Reflection;
using System.Xaml;

namespace SL5MarkupExtension.MarkupExtensions
{
    /// <summary>
    ///  Classe permettant de faire une MarkupExtension XAML pour récupérer les valeurs de champs ou propriétés.
    /// </summary>
    public class Static : IMarkupExtension<Object>
    {
        #region Data
        private String _member;
        private Type _memberType;
        #endregion

        #region Ctors
        /// <summary>
        ///  Crée une instance de la classe permettant de faire une MarkupExtension XAML pour récupérer les valeurs de champs ou propriétés.
        /// </summary>
        public Static()
        {
        }
        #endregion

        #region MarkupExtension implementation
        /// <summary>
        ///  Obtient un objet correspondant au type fournit en paramètre. Permet de récupérer un champ ou une propriété
        /// </summary>
        /// <param name="serviceProvider">Service permettant de récuperer le service utilisé pour les MarkupExtension.</param>
        /// <returns>
        ///  Un objet correspondant à la chaine fournie en paramettre (Member)
        /// </returns>
        public Object ProvideValue(IServiceProvider serviceProvider)
        {
            Object ret = null;
            Boolean typeResolveFailed = true;
            Type type = MemberType;
            String fieldMemberName = null;
            String fullFieldMemberName = null;

            if (Member != null)
            {
                if (MemberType != null)//on a le type et le membre
                {
                    fieldMemberName = Member;
                    fullFieldMemberName = String.Format("{0}.{1}", type.FullName, Member);
                }
                else //on a pas le type, on regarde si la chaine est bien formatée ex : local:MyEnum.MyEnumeValue et on essaie de résoudre le type
                {
                    Int32 index = Member.IndexOf('.');

                    if (index >= 0)
                    {
                        string typeName = Member.Substring(0, index);

                        if (!String.IsNullOrEmpty(typeName))
                        {
                            IXamlTypeResolver xamlTypeResolver = serviceProvider.GetService(typeof(IXamlTypeResolver)) as IXamlTypeResolver;

                            if (xamlTypeResolver != null)
                            {
                                type = xamlTypeResolver.Resolve(typeName);
                                fieldMemberName = Member.Substring(index + 1); //, Member.Length - index - 1
                                typeResolveFailed = String.IsNullOrEmpty(fieldMemberName);
                            }
                        }
                    }
                }

                if (typeResolveFailed)
                {
                    throw new InvalidOperationException("Member");
                }
                else
                {
                    if (type.IsEnum) //si c'est un enum alors on essaie de résoudre le membre
                    {
                        ret = Enum.Parse(type, fieldMemberName, true);
                    }
                    else //ce n'est pas un enum : probablement un champ ou une propriété
                    {
                        Boolean fail = true;

                        FieldInfo field = type.GetField(fieldMemberName, BindingFlags.Public | BindingFlags.FlattenHierarchy | BindingFlags.Static);

                        if (field != null)
                        {
                            fail = false;
                            ret = field.GetValue(null);
                        }
                        else//ce n'est pas un champ, on regarde si c'est une propriété
                        {
                            //on regarde si c'est une propriété
                            PropertyInfo property = type.GetProperty(fieldMemberName, BindingFlags.Public | BindingFlags.FlattenHierarchy | BindingFlags.Static);

                            if (property != null)//c'est une propriété
                            {
                                fail = false;
                                ret = property.GetValue(null, null);
                            }
                        }

                        if (fail)
                        {
                            throw new ArgumentException(fullFieldMemberName);
                        }
                    }
                }
            }
            else
            {
                throw new InvalidOperationException();
            }

            return ret;
        }
        #endregion

        #region Membres
        /// <summary>
        /// Obtient ou définit le membre statique à résoudre ex : local:MyEnum.MyEnumValue si pas de MemberType sinon MyEnumValue
        /// </summary>
        public string Member
        {
            get
            {
                return _member;
            }
            set
            {
                if (value == null)
                {
                    throw new ArgumentNullException("Member value");
                }

                _member = value;
            }
        }

        /// <summary>
        /// Obtient ou définit le type du membre à résoudre
        /// </summary>
        public Type MemberType
        {
            get
            {
                return _memberType;
            }
            set
            {
                if (value == null)
                {
                    throw new ArgumentNullException("MemberType value");
                }

                _memberType = value;
            }
        }
        #endregion
    }
}

Action !

Sample objects

Nous définissons ici une classe Module contenant 3 constantes


public class Modules
    {
        public static readonly string ModuleA = "NewsModule";
        public static readonly string ModuleB = "MediasModule";
        public static readonly string ModuleC = "CalendarModule";
    }

Puis un enum contenant 3 valeurs


    public enum Gender
    {
        Homme,
        Femme,
        Indefini
    }

Mise en pratique

Tout d’abord vous devez référencer votre MarkupExtension et les objets que vous souhaitez référencer.

xmlns:markup="clr-namespace:SL5MarkupExtension.MarkupExtensions"
xmlns:local="clr-namespace:SL5MarkupExtension"

Puis vous n’avez plus qu’à l’utiliser dans votre XAML avec la syntaxe suivante :

{markup:Static Member=local:Modules.ModuleA}

Exemple complet

<UserControl x:Class="SL5MarkupExtension.MainPage"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:markup="clr-namespace:SL5MarkupExtension.MarkupExtensions"
             xmlns:local="clr-namespace:SL5MarkupExtension"
             xmlns:app="clr-namespace:System.Windows;assembly=System.Windows">

    <Grid x:Name="LayoutRoot"
          Background="White">
        <StackPanel VerticalAlignment="Center"
                    HorizontalAlignment="Center">
            <!--CONST-->
            <TextBlock Text="{markup:Static Member=local:Modules.ModuleA}" />
            <TextBlock Text="{markup:Static Member=local:Modules.ModuleB}" />

            <!--CLASS-->
            <TextBlock Text="{Binding Path=InstallState, Source={markup:Static Member=app:Application.Current}}" />

            <!--ENUM-->
            <TextBlock Text="{Binding Source={markup:Static Member=local:Gender.Homme}}" />
        </StackPanel>
    </Grid>
</UserControl>

Résultat

silverlight-x-static-markupextension-like-wpf

Le résultat est très intéressant et ouvre de nouvelles possibilités dans le développement Silverlight 🙂

 

Update 4/7/2012 :
Said Outgajjouft m’a fait part d’une refactorisation du code pour le rendre plus clair, merci à lui 😉

using System;
    using System.Reflection;
    using System.Windows.Markup;
    using System.Xaml;


    /// <summary>
    /// Provides WPFs StaticExtension to Silverligth.
    /// The Static class implements a markup extension that returns static field and property references. 
    /// </summary>
    public class StaticExtension : IMarkupExtension<object>
    {
        /// <summary>"StaticExtension  must have Member property set before ProvideValue can be called.</summary>
        private const string MarkupExtensionStaticMember = "StaticExtension must have Member property set before ProvideValue can be called.";
        /// <summary>'{0}' StaticExtension value cannot be resolved to an enumeration, static field, or static property.</summary>
        private const string MarkupExtensionBadStatic = "'{0}' StaticExtension value cannot be resolved to an enumeration, static field, or static property.";
        /// <summary>Markup extension '{0}' requires '{1}' be implemented in the IServiceProvider for ProvideValue.</summary>
        private const string MarkupExtensionNoContext = "Markup extension '{0}' requires '{1}' be implemented in the IServiceProvider for ProvideValue.";

        private string _member;
        private Type _memberType;


        /// <summary>Gets or sets a member name string that is used to resolve a static field or property based on the service-provided type resolver.</summary>
        /// <exception cref="ArgumentNullException">Attempted to set <see cref="Member"/> to <b>null</b>.</exception>
        public string Member
        {
            get { return _member; }
            set
            {
                if (value == null)
                    throw new ArgumentNullException("value");

                _member = value;
            }
        }


        /// <summary>Gets or sets the <see cref="Type"/> that defines the static member to return.</summary>
        /// <exception cref="ArgumentNullException">Attempted to set <see cref="MemberType"/> to <b>null</b>.</exception>
        public Type MemberType
        {
            get { return _memberType; }
            set
            {
                if (value == null)
                    throw new ArgumentNullException("value");

                _memberType = value;
            }
        }


        /// <summary>
        /// Returns an object value to set on the property where you apply this extension.
        /// For <see cref="StaticExtension"/>, the return value is the static value that is evaluated for the requested static member.
        /// </summary>
        /// <param name="serviceProvider">
        /// An object that can provide services for the markup extension. The service provider is expected to provide a service 
        /// that implements a type resolver (<see cref="IXamlTypeResolver"/>).
        /// </param>
        /// <returns>The static value to set on the property where the extension is applied.</returns>
        /// <exception cref="InvalidOperationException">The <see cref="Member"/> for the extension is <b>null</b> at the time of evaluation.</exception>
        /// <exception cref="ArgumentException">
        /// <p>Some part of the <see cref="Member"/> string did not parse properly</p>
        /// <p>-or-</p>
        /// <p><paramref name="serviceProvider"/> did not provide a service for <see cref="IXamlTypeResolver"/></p>
        /// <p>-or-</p>
        /// <p><see cref="Member"/> value did not resolve to a static member.</p>
        /// </exception>
        /// <exception cref="ArgumentNullException"><paramref name="serviceProvider"/> is <b>null</b>.</exception>
        public object ProvideValue(IServiceProvider serviceProvider)
        {
            var member = Member;
            var memberType = MemberType;
            string memberName;


            if (member == null)
                throw new InvalidOperationException(MarkupExtensionStaticMember);

            if (memberType != null)
            {
                memberName = member;
            }
            else
            {
                var index = member.IndexOf('.');
                if (index == -1)
                    throw new ArgumentException(string.Format(MarkupExtensionBadStatic, member));

                var qualifiedTypeName = member.Substring(0, index);
                if (qualifiedTypeName.Length == 0)
                    throw new ArgumentException(string.Format(MarkupExtensionBadStatic, member));

                if (serviceProvider == null)
                    throw new ArgumentNullException("serviceProvider");

                var xamlTypeResolver = serviceProvider.GetService(typeof(IXamlTypeResolver)) as IXamlTypeResolver;
                if (xamlTypeResolver == null)
                    throw new ArgumentException(string.Format(MarkupExtensionNoContext, GetType().Name, typeof(IXamlTypeResolver).Name));

                memberType = xamlTypeResolver.Resolve(qualifiedTypeName);
                memberName = member.Substring(index + 1);
                if (memberName.Length == 0)
                    throw new ArgumentException(string.Format(MarkupExtensionBadStatic, member));
            }

            if (memberType.IsEnum)
                return Enum.Parse(memberType, memberName, true);

            var field = memberType.GetField(memberName, BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Static);
            if (field != null)
                return field.GetValue(null);

            var property = memberType.GetProperty(memberName, BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Static);
            if (property != null)
                return property.GetValue(null, null);

            throw new ArgumentException(string.Format(MarkupExtensionBadStatic, memberType.FullName + "." + memberName));
        }
    }

 

Catégories :Silverlight, Silverlight 5, WPF

[SL5] : Silverlight 5 Implicit DataTemplate

Très connu en WPF, la notion de DataTemplate implicites est nouvelle en Silverlight 5. Afin de comprendre la puissance et la simplicité de codage que cela apporte nous allons réaliser deux exemples représentatifs de son utilisation.

Cas d’utilisation pour une composition d’IHM

Ce mode là est souvent utilisé en WPF pour réaliser une composition de l’interface via le patter ViewModelFirst qui consiste à substituer une donnée (ex classe) par une vue spécifique.

Pour illustrer cela nous allons réaliser 3 classes basiques ClassA, ClassB et ClassC et une classe GlobalViewModel contenant 3 propriétées PropertyA de type ClassA, PropertyB de type ClassB et PropertyC de type ClassC.

Les classes

 public class ClassA
    {
    }

    public class ClassB
    {
    }

    public class ClassC
    {
    }

    public class GlobalViewModel
    {
        public GlobalViewModel()
        {
            PropertyA = new ClassA();
            PropertyB = new ClassB();
            PropertyC = new ClassC();
        }
        public ClassA PropertyA
        {
            get;
            set;
        }

        public ClassB PropertyB
        {
            get;
            set;
        }

        public ClassC PropertyC
        {
            get;
            set;
        }
    }

Controles Utilisateurs

Nous allons réaliser 3 UserControls UC1, UC2 et UC3 correspondants respectivement aux classes ClassA, ClassB et ClassC.

UC1
<UserControl x:Class="Silverlight5Tests.UC1"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid Background="GreenYellow">
        <TextBlock Text="A"
                   FontSize="150"
                   FontWeight="Bold"
                   VerticalAlignment="Center"
                   HorizontalAlignment="Center" />

    </Grid>
</UserControl>
UC2
<UserControl x:Class="Silverlight5Tests.UC2"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Grid Background="DarkCyan">
        <TextBlock Text="B"
                   FontSize="150"
                   FontWeight="Bold"
                   VerticalAlignment="Center"
                   HorizontalAlignment="Center" />

    </Grid>
</UserControl>

UC3
<UserControl x:Class="Silverlight5Tests.UC3"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid Background="BlanchedAlmond">
        <TextBlock Text="C"
                   FontSize="150"
                   FontWeight="Bold"
                   VerticalAlignment="Center"
                   HorizontalAlignment="Center" />

    </Grid>
</UserControl>

La vue principale

Ensuite nous allons créer une vue principale dans laquelle nous souhaitons afficher les 3 contrôles de façon automatique

<navigation:Page x:Class="Silverlight5Tests.DataTypeTest"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
                 xmlns:local="clr-namespace:Silverlight5Tests"
                 Title="DataType Page">
    <navigation:Page.Resources>
        <DataTemplate DataType="local:ClassA">
            <local:UC1 />
        </DataTemplate>
        <DataTemplate DataType="local:ClassB">
            <local:UC2 />
        </DataTemplate>
        <DataTemplate DataType="local:ClassC">
            <local:UC3 />
        </DataTemplate>
    </navigation:Page.Resources>

    <Grid x:Name="LayoutRoot">
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <!--UC1-->
        <ContentControl Content="{Binding PropertyA}"
                        HorizontalContentAlignment="Stretch"
                        VerticalContentAlignment="Stretch" />
        <!--UC2-->
        <ContentControl Content="{Binding PropertyB}"
                        HorizontalContentAlignment="Stretch"
                        VerticalContentAlignment="Stretch"
                        Grid.Column="1" />
        <!--UC3-->
        <ContentControl Content="{Binding PropertyC}"
                        HorizontalContentAlignment="Stretch"
                        VerticalContentAlignment="Stretch"
                        Grid.Row="1"
                        Grid.ColumnSpan="2" />

    </Grid>
</navigation:Page>

Puis la magie s’effectue grâce a la nouvelle propriété DataType héritée de ce que nous connaissons en WPF. Vous pouvez mettre cela en ressource locale ou tout simplement en ressource globale à l’application si vous en avez besoin à d’autres endroits.
Nous réalisons 3 DataTemplate représentants nos 3 classes avec leurs UserControls associés.

  <navigation:Page.Resources>
        <DataTemplate DataType="local:ClassA">
            <local:UC1 />
        </DataTemplate>
        <DataTemplate DataType="local:ClassB">
            <local:UC2 />
        </DataTemplate>
        <DataTemplate DataType="local:ClassC">
            <local:UC3 />
        </DataTemplate>
    </navigation:Page.Resources>

Résultat

image

L’intérêt de cette solution est de s’abstraire le plus possible et de ne pas avoir à référencer un UserControl à chaque fois qu’on en a besoin. Ainsi le changement du DataTemplate provoquera automatiquement le changement du comportement de votre application sans avoir à modifier l’ensemble de l’application.

Cas d’une liste hétérogène

Prenons le cas d’un liste de User contenant quelques champs comme le nom, le prénom et une ville. Nous disposons aussi de deux autres classes dérivées nommées NormalUser et SuperUser.

Grace au DataTemplate explicites nous pouvons réaliser une affichage différent pour chaque types de User. Tout cela en quelques lignes de XAML…

Notre modèle de données


    public abstract class UserBase
    {
        public String LastName
        {
            get;
            set;
        }

        public String FirstName
        {
            get;
            set;
        }

        public String Town
        {
            get;
            set;
        }
    }

    public class NormalUser : UserBase
    {
    }

    public class SuperUser : UserBase
    {
        public String SampleProperty
        {
            get;
            set;
        }
    }

UserControl d’un utilisateur normal

<UserControl x:Class="Silverlight5Tests.UserItemView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Border BorderBrush="#FF8D8D8D" BorderThickness="0,0,0,1" Background="#FFCDD7FF">

		<StackPanel Margin="5">
			<TextBlock Text="{Binding LastName}" />
			<TextBlock Text="{Binding FirstName}" />
		</StackPanel>
	</Border>
</UserControl>

UserControl d’un super utilisateur

<UserControl x:Class="Silverlight5Tests.SuperUserItemView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Border BorderThickness="0,0,0,1" Background="#FFFFB396" BorderBrush="#FF8D8D8D">

		<StackPanel Margin="5">
			<TextBlock Text="{Binding LastName}" />
			<TextBlock Text="{Binding FirstName}" />
		</StackPanel>
	</Border>
</UserControl>

Affichage de la liste des utilisateurs

Pour cela il suffit de déclarer les DataTemplates explicites correspondant aux classes NormalUser et SuperUser.

XAML
<navigation:Page x:Class="Silverlight5Tests.ImplicitTemplates"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
                 xmlns:local="clr-namespace:Silverlight5Tests"
                 Title="ImplicitTemplates Page">
    <Grid x:Name="LayoutRoot">
        <ItemsControl ItemsSource="{Binding}">
            <ItemsControl.Resources>
                <DataTemplate DataType="local:NormalUser">
                    <local:UserItemView />
                </DataTemplate>
                <DataTemplate DataType="local:SuperUser">
                    <local:SuperUserItemView />
                </DataTemplate>
            </ItemsControl.Resources>
        </ItemsControl>
    </Grid>
</navigation:Page>

CS
using System;
using System.Collections.Generic;
using System.Windows.Controls;

namespace Silverlight5Tests
{
    public partial class ImplicitTemplates : Page
    {
        public ImplicitTemplates()
        {
            InitializeComponent();

            DataContext = new List()
            {
                new NormalUser()
                {
                    LastName = "LOUGE",
                    FirstName = "Stéphane",
                    Town = "Biarritz"
                },
                 new SuperUser()
                {
                    LastName = "GATES",
                    FirstName = "Bill",
                    Town = "Seattle"
                },
                 new NormalUser()
                {
                    LastName = "HULOT",
                    FirstName = "Nicolas",
                    Town = "Paris"
                },
                new NormalUser()
                {
                    LastName = "VIGIE",
                    FirstName = "Julie",
                    Town = "Iron"
                }
            };
        }
    }

}

Resultat

Silverlight5ImplicitDataTemplate

Catégories :Silverlight, Silverlight 5

[SL5] : Silverlight 5 TextSearch on ItemsControl

Autre nouveauté de Silverlight 5 est la faculté de pouvoir rechercher des informations sans un itérateur grace au clavier en tappant du texte.

A titre d’exemple voici un objet tout simple représentant un utilisateur :

 public class User
    {
        public String FirstName
        {
            get;
            set;
        }
        public Int32 Age
        {
            get;
            set;
        }
    }

Maintenant nous souhaiterions pouvoir selectionner un user dans la liste en foncion de ce que nous tappons au clavier, pour cela il suffit de rajouter la propriété attachée TextSearch.TextPath= »NomDeLaProprieteOuLaRechercheDoitEtreFaite » :

  <ListBox ItemsSource="{Binding}"
                 TextSearch.TextPath="FirstName"
                 Width="200"
                 Height="200"
                 HorizontalAlignment="Center"
                 VerticalAlignment="Center"
                 DisplayMemberPath="FirstName" />

Puis une petit séquence de code pour notre jeu de données factice :

InitializeComponent();

            DataContext = new List<User>()
            {
                new User()
                {
                    FirstName= "Jacques",
                    Age=20
                },
                new User()
                {
                    FirstName= "Nicolas",
                    Age=20
                },
                 new User()
                {
                    FirstName= "Pierre",
                    Age=20
                },
                 new User()
                {
                    FirstName= "Paul",
                    Age=20
                },
                 new User()
                {
                    FirstName= "Antoine",
                    Age=20
                },
                 new User()
                {
                    FirstName= "Rémi",
                    Age=20
                },
                 new User()
                {
                    FirstName= "Julie",
                    Age=20
                },
                 new User()
                {
                    FirstName= "Stéphane",
                    Age=20
                },
                 new User()
                {
                    FirstName= "Stéphanie",
                    Age=20
                },
                 new User()
                {
                    FirstName= "Edmond",
                    Age=20
                },
                 new User()
                {
                    FirstName= "Cynthia",
                    Age=20
                },
                 new User()
                {
                    FirstName= "Jean",
                    Age=20
                },
                new User()
                {
                    FirstName= "Bill",
                    Age=20
                },
                new User()
                {
                    FirstName= "Steve",
                    Age=20
                }
            }.OrderBy(x => x.FirstName);

Ainsi en tappant « S » cela a pour effet de sélectionner directement l’occurence Stéphane, si vous continuez jusqu’à « Stéphani » la ListBox sélectionnera « Stéphanie ».

ListBoxTextSearchSilverlight5

Catégories :Silverlight, Silverlight 5

[SL5] : Silverlight 5 Binding news

Dans cette nouvelle mouture, Silverlight 5 rattrape petit à petit une partie de son retard sur WPF. Nous allons voir ici que nous pouvons à présent utiliser les attributs FindAncestor et AncestorType afin d’effectuer une recherche sur un parent grace à une notion de niveau et de type recherché.

Quand la l’élément source est égal au plus proche des parents d’un type donné (ici renvoie Grille1)

<Grid x:Name="Grille1">
<StackPanel>
<TextBlock Text="{Binding Name,  RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Grid}}" />
</StackPanel>
</Grid>

Quand vous souhaitez le nième parent d’un type donné ex le deuxième parent du type Grid (ayant le nom Grille1 et non Grille2 comme dans l’exemple précédent)

<Grid x:Name="LayoutRoot">
        <Grid x:Name="Grille1">
            <Grid x:Name="Grille2">
                <StackPanel>
                    <TextBlock Text="{Binding Name, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Grid, AncestorLevel=2}}" />
                </StackPanel>
            </Grid>
        </Grid>
    </Grid>
Catégories :Silverlight, Silverlight 5

[SL5] : Silverlight 5 XAML Debugging

Il est a présent possible d’ajouter un BreakPoint directement dans le XAML afin de pouvoir identifier les erreurs de Binding par exemple.

 

Ajout d’un BreakPoint sur le XAML

Pour cela il suffit d’ajouter de point d’arrêt comme vous le faite habituellement dans les classes .net.

image

 

Visionnage des informations d’un Binding

A l’exécution et au changement de valeur d’un Binding vous en serez notifié et vous pourrez identifier les erreurs qui autrefois auraient nécessité un converter…

image

 

Gestion des erreurs

Ici nous modifions volontairement Value en ValueA afin de provoquer une erreur de Binding.

Dans le détail de l’erreur nous pouvons voir explicitement l’erreur qui a provoqué le dysfonctionnement :

image

Ainsi dans Error nous pouvons voir :

BindingState    {Error: System.Exception: Erreur System.Windows.Data : erreur de chemin d’accès BindingExpression : propriété ‘ValueA’ introuvable sur ‘System.Windows.Controls.Slider Minimum:0 Maximum:1000 Value:0’ ‘System.Windows.Controls.Slider’ (HashCode=17271312). BindingExpression : Path=’ValueA’ DataItem=’System.Windows.Controls.Slider Minimum:0 Maximum:1000 Value:0′ (HashCode=17271312); l’élément cible est ‘System.Windows.Controls.TextBlock’ (Name= »); la propriété cible est ‘CharacterSpacing’ (type ‘System.Int32’)..}    object {System.Windows.Data.Debugging.BindingDebugState}

ValueA = NotFound Sourire

Catégories :Silverlight, Silverlight 5