[Telerik] : SelectedItem dans les BarSeries du RadChartView

7 décembre 2012 2 commentaires

Je partage une petite astuce permettant de disposer de la sélection sur le composant RangeBar du RadCartesianChart de Telerik.
Nativement le composant n’offre pas un moyen simple de connaitre l’élément actuellement sélectionné via le pattern MVVM.
Pour cela j’ai dérivé le composant RadSerie afin de lui apporter cette fonctionnalité, dont voici le code :


/// <summary>
    /// Extended <see cref="BarSeries"/> that support a selected item
    /// </summary>
    public class ExtendedBarSeries : BarSeries
    {
        #region Members

        private ChartSelectionBehavior _selectionBehavior;

        #endregion

        #region DPs

        /// <summary>
        /// Define the selected item dependency property
        /// </summary>
        public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register("SelectedItem", typeof(Object), typeof(ExtendedBarSeries), new PropertyMetadata(null, SelectedItemChanged));

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the current selected item
        /// </summary>
        public Object SelectedItem
        {
            get
            {
                return GetValue(SelectedItemProperty);
            }
            set
            {
                SetValue(SelectedItemProperty, value);
            }
        }

        #endregion

        #region Handlers

        /// <summary>
        /// Occurs when the presenter has been successfully attached to its owning Telerik.Windows.Controls.ChartView.RadChartBase instance.
        /// </summary>
        protected override void OnAttached()
        {
            base.OnAttached();

            _selectionBehavior = Chart.Behaviors.OfType<ChartSelectionBehavior>().FirstOrDefault();

            if (_selectionBehavior == null)
            {
                _selectionBehavior = new ChartSelectionBehavior();
                Chart.Behaviors.Add(_selectionBehavior);
            }

            _selectionBehavior.SelectionChanged += OnSelectionBehaviorSelectionChanged;
        }

        /// <summary>
        /// Occurs when the presenter has been successfully detached from its owning Telerik.Windows.Controls.ChartView.RadChartBase instance.
        /// </summary>
        /// <param name="oldChart">The old chart instance</param>
        protected override void OnDetached(RadChartBase oldChart)
        {
            base.OnDetached(oldChart);

            if (_selectionBehavior != null)
            {
                _selectionBehavior.SelectionChanged -= OnSelectionBehaviorSelectionChanged;
                oldChart.Behaviors.Add(_selectionBehavior);
                _selectionBehavior = null;
            }
        }

        /// <summary>
        /// Occurs when the chart selection has changed.
        /// </summary>
        /// <param name="sender">The sender</param>
        /// <param name="e">The chart selection arguments</param>
        private void OnSelectionBehaviorSelectionChanged(object sender, ChartSelectionChangedEventArgs e)
        {
            DataPoint dp = Chart.SelectedPoints.FirstOrDefault(p => p.IsSelected);

            SetValue(SelectedItemProperty, (dp != null) ? dp.DataItem : null);
        }

        /// <summary>
        /// Occurs when the selected item dependency property value changed
        /// </summary>
        /// <param name="d">The dependecy object</param>
        /// <param name="e">The dependency value changes</param>
        private static void SelectedItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var serie = d as ExtendedBarSeries;

            if (serie != null)
            {
                List<CategoricalDataPoint> serieItems = serie.DataPoints.OfType<CategoricalDataPoint>().ToList();

                if (serie._selectionBehavior != null)
                {
                    if (e.NewValue == null)
                    {
                        serie._selectionBehavior.ClearSelection(true, false);
                    }
                    else
                    {
                        CategoricalDataPoint p = serieItems.FirstOrDefault(dp => dp.DataItem == e.NewValue);

                        if (p != null)
                        {
                            if (!serie.Chart.SelectedPoints.Contains(p))
                            {
                                serie._selectionBehavior.ClearSelection(true, false);
                                p.IsSelected = true;
                            }
                        }
                    }
                }
            }
        }

        #endregion
    }

Maintenant a des fins de tests nous faisons rapidement deux classes pour simuler les données:

    public class Data
    {
        public String X
        {
            get;
            set;
        }
        public Int32 Y
        {
            get;
            set;
        }
    }

Puis un manager de données :

 public class DataManager : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private Data _selectedItem;
        private readonly List<Data> _items;

        public DataManager()
        {
            Random r = new Random();
            _items = new List<Data>();

            for (int i = 0; i < 20; i++)
            {
                _items.Add(new Data()
                {
                    X = i.ToString(),
                    Y = r.Next(0, 30)
                });
            }
        }

        public List<Data> Items
        {
            get
            {
                return _items;
            }
        }

        public Data SelectedItem
        {
            get
            {
                return _selectedItem;
            }
            set
            {
                if (_selectedItem == value)
                    return;

                _selectedItem = value;
                OnPropertyChanged("SelectedItem");
            }
        }

        public void OnPropertyChanged(String propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

Enfin nous créons une instance de la classe DataManager que nous affectons au DataContext de notre vue

/// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            DataContext = new DataManager();
        }
    }

Pour terminer nous créons une vue avec le graphique Telerik, notre composant ExtendedBarSeries et une ComoboBox nous permettant d’effectuer une sélection « programmé » par autre chose qu’un click sur le graphe.

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
        xmlns:controls="clr-namespace:TelerikChartViewSelection"
        x:Class="TelerikChartViewSelection.MainWindow"
        Title="MainWindow"
        Height="350"
        Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition />
        </Grid.RowDefinitions>

        <!--COMBO-->
        <ComboBox ItemsSource="{Binding Items}"
                  SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
                  DisplayMemberPath="X" />

        <!--CHART-->
        <telerik:RadCartesianChart Grid.Row="1">

            <telerik:RadCartesianChart.HorizontalAxis>
                <telerik:CategoricalAxis />
            </telerik:RadCartesianChart.HorizontalAxis>

            <telerik:RadCartesianChart.VerticalAxis>
                <telerik:LinearAxis />
            </telerik:RadCartesianChart.VerticalAxis>

            <telerik:RadCartesianChart.Grid>
                <telerik:CartesianChartGrid MajorLinesVisibility="Y" />
            </telerik:RadCartesianChart.Grid>

            <telerik:RadCartesianChart.SelectionPalette>
                <telerik:ChartPalette>
                    <telerik:ChartPalette.GlobalEntries>
                        <telerik:PaletteEntry Fill="Orange" />
                    </telerik:ChartPalette.GlobalEntries>
                </telerik:ChartPalette>
            </telerik:RadCartesianChart.SelectionPalette>

            <controls:ExtendedBarSeries ItemsSource="{Binding Items}"
                                        SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
                                        ValueBinding="Y"
                                        CategoryBinding="X" />
        </telerik:RadCartesianChart>

    </Grid>
</Window>

Enfin voici le résultat final :

Telerik-BarSerie-RadChartView-Selection-MVVM

Vous pouvez désormais manipuler en MVVM le composant BarSeries 🙂

Code source de l’exemple (à renommer) : TelerikChartViewSelection.7z

Publicités
Catégories :RadChartView, Silverlight, Telerik, WPF

[Promo] : Bordeaux onLive v1.2

Petit article pour vous parler de la sortie de la mise ajour 1.2 de l’application Bordeaux onLive sur WP7 !

Plus d’informations sur  : http://www.bordeaux-onlive.com

Nouvelles fonctionnalités

  • Ajout de la possibilité d’épingler le trafic de la rocade sur l’écran d’accueil
  • Ajout de l’aperçu de la rocade sur la tuile
  • Ajout du trafic intérieur de la rocade
  • Ajout de la fonctionnalité TBC tant demandée !
  • Ajout de la liste des lignes de Bus
  • Ajout de la liste des lignes de Tramways
  • Ajout de la liste des terminus d’une ligne
  • Ajout de la liste des arrêts d’une ligne de Bus / Tram
  • Ajout de la liste des prochains passages théoriques d’un Bus / Tram à un arrêt
  • Ajout du détail du trajet avec horaires théoriques jusqu’à la fin

Screenshots

                

Disponible gratuitement sur le marketplace

download

[Blend] : Carousel étape par étape pour designer / graphistes sans coder

Bonjour à tous, voici un petit article concernant l’utilisation avancée du composant PathListBox pour réaliser un Carousel.

Suite à une question pertinente d’un designer / graphiste souhaitant créer un carousel le plus simplement du monde et ne connaissant pas forcement le développement WPF / Silverlight .

L’objectif de cet article est de montrer que nous pouvons arriver à réaliser des visuels et interactions simplement par un graphiste. L’alimentation des données pouvant rester à la charge du développeur.

Avant tout rendez-vous sur le site : http://expressionblend.codeplex.com/releases/view/57990 et téléchargez le pack d’extention pour les PathListBox de Microsoft Expression Blend.

Créez un projet WPF (ou Silverlight) et nommez le pour l’exemple « WpfSampleCarousel ».

Créez un UserControl nommé “CarouselUserControl”

Ajoutez une grille avec trois colonnes. Dans la première et la dernière ajoutez un bouton (précédent et suivant).

Et le composant PathListBox

Step1

Ensuite, créez un ‘path’ de la forme de vous souhaitez (toujours dans la deuxième colonne)

Step2

Cliquez sur votre PathListBox et cliquez sur la cible sans lacher et pointez votre souris sur le path créé ci-dessus.

Ensuite nous allons configurer le PathListBox, modifiez les paramètres comme présentés ci-dessous (Distibution : Even, Capacity : un nombre impair si vous voulez un effet central, Start : 10%, FillBehavior : NoOverlap et surtout cochez WrapItems)

Step4

A titre d’exemple ajoutons des rectangles à notre PathListBox afin de pouvoir visualiser le ‘Carousel’ vous pouvez y mettre ce que vous souhaitez (ex images)

<Rectangle MinWidth="100" MinHeight="100" Fill="#FFFF3237"/>
			<Rectangle MinWidth="100" MinHeight="100" Fill="#FF89C122"/>
			<Rectangle MinWidth="100" MinHeight="100" Fill="#FFFEB63E"/>
			<Rectangle MinWidth="100" MinHeight="100" Fill="#FF2ACC55"/>
			<Rectangle MinWidth="100" MinHeight="100" Fill="#FFFE198E"/>
			<Rectangle MinWidth="100" MinHeight="100" Fill="#FF949494"/>
			<Rectangle MinWidth="100" MinHeight="100" Fill="#FF58A2E6"/>
			<Rectangle MinWidth="100" MinHeight="100" Fill="#FF8A144F"/>
			<Rectangle MinWidth="100" MinHeight="100" Fill="#FF37E4F5"/>
			<Rectangle MinWidth="100" MinHeight="100" Fill="#FFA4D9FA"/>

 

Nous obtenons visuellement un ‘Carousel’ plutot satisfaisant !

Ajoutons un peu d’interactivité ! Pour cela ajoutez un ‘Behavior’ nommé ‘PathListBoxScrollBehavior’ sur votre PathListBox en faisant un glisser déposer.

Configurons ce Behavior, pour cela cliquez dessus et cliquez sur le petit plus de DecrementCommand, IncrementCommand et ScrollSelectedCommand afin d’y ajouter un ‘EventTrigger’ présent ci-dessous

Puis configurez DecrementCommand, pour cela cliquez sur EventTrigger dans le SourceName cliquez sur la cible et glissez votre souris sur le bouton de gauche.

Sélectionnez ‘Click’ dans la zone EventName.

Répétez pour IncrementCommand, en pointant vers le bouton de droite.

Pour la zone ScrollSelectedCommand selectionnez SelectionChanged dans EventName (sourcename doit correspondre à votre PathListBox)

Vous pouvez si vous le souhaitez modifier la vitesse, et la façon dont les éléments se déplacent.

Si vous exécutez votre application votre ‘carousel’ est pleinement fonctionnel.

Nous allons à présent voir comment rendre celui ci plus sympathique visuellement. Nous allons faire en sorte que nos éléments soient plus petits sur les extrémités et que l’élément central soit centré 🙂

Pour cela faites un clic droit sur votre PathListBox Edit Additional templates > Edit Generated Container > Edit a Copy

Groupez l’élément principal dans une grille en faisant un clic droit sur l’élément racine :

Ajoutez un composant ‘PathListBoxItemTransformer’ en le glissant dans votre élément racine.

Vous obtenez :

Ensuite glissez la grille du bas dans le PathListBoxItemTransformer, vous obtenez :

Ensuite nous allons modifier le comportement d’un élément par rapport aux autres, pour cela cliquez sur ‘PathListBoxItemTransformer’ et allez dans le panneau des propriétés à droite, modifiez les options OpacityRange (50% d’opacité aux extrémités dans ce cas), ScaleRange (20% de la taille d’origine aux extrémités et 150% au centre), Ease à SineOut et surtout la propriété IsCentered pour disposer d’un élément central :

Nous obtenons ainsi :

Vous n’avez plus qu’à cliquez sur le ‘path’ (ici rouge) définit au début de l’exercice et de mettre transparent afin de ne plus le voir.

Dernière chose déposez votre UserControl dans votre fenêtre principale (via Assets si vous êtes designer ou tout simplement dans le xaml si vous savez le faire en référençant le bon namespace)

Exécutez votre application et vous disposez d’un carousel plutot sympathique facilement réalisable par un Designer sans avoir à faire le moindre code 😀

L’ensemble des sources de cet exemple sont disponibles ici : WpfSampleCarousel.zip (renommez le .doc en .zip)

Bon design 🙂

Catégories :Blend, Silverlight, WPF Étiquettes : ,

[Promo] : Sortie de U-Telemarket sur WP7

Petit article afin de vous faire partager une petite application que j’ai pu développer.

L’application U-Telemarket vous permet à tout moment de faire vos courses et de vous faire livrer chez vous, à l’heure qui vous convient !

Avec l’application U Telemarket.fr vous pouvez désormais :

-Créer ou rattacher votre compte sur votre mobile,
-Accéder directement aux promotions du jour,
-Faire vos courses par rayons et sous-rayons,
-Afficher chaque fiche produit et choisir la quantité à ajouter à votre panier,
-Valider votre panier : liste des produits et quantités choisies,
-Sélectionner votre adresse de facturation et une ou plusieurs adresses de livraison,
-Choisir votre créneau de livraison,
-Régler en direct de vos achats,
-Recevoir votre récapitulatif directement sur votre mobile.

download

Catégories :Windows Phone 7

[Promo] : Sortie de Bordeaux onLive sur WP7

Petit article pour vous parler de l’application Bordeaux onLive que je viens de sortir sur WP7 et que vous pouvez dès à présent trouver sur le marketplace !

flyer-bordeaux-onlive-wp7-windows-phone-7

Retrouvez gratuitement toutes les informations officielles de la CUB et bien plus encore grace à l’application Bordeaux onLive disponible sur Windows Phone 7!

L’essentiel VCub

Elle aidera à vous déplacer entre chaque station du VCub et faire le bon choix selon les disponibilités des cycles et des emplacements.

Trafic de la rocade en temps réel

Cette fonctionnalité vous permettra de gérer au mieux vos trajets en voiture.

Informations sur les parking publics et parc relais

Les informations sur les parkings et parcs relais de bordeaux vous permettront de garer votre véhicule en toute tranquilité et de gérer au mieux vos itinéraires.

 

Plus d’informations sur le site web associé : bordeaux-onlive

ou tout simplement sur le marketplace

download

 

MAJ du 12/02/2012

  • Fixed Correction de bugs.
  • New Localisation de l’application en Anglais, Français et Italien.
  • New Liste des parkings publics avec le nombre de places disponibles.
  • New Détails d’un parking public.
  • New Liste des parcs relais.
  • New Détails d’un parc relais avec la capacité voiture, 2 roues, handicapés et électrique.
  • New Possibilité de désactiver la fonction de localisation dans l’application (paramètres).

[WP7] : TextBox avec une indication visuelle (Watermark)

Nous allons voir aujourd’hui comment faire une TextBox contenant une indication visuelle pour l’utilisateur en Windows Phone 7, tout cela de la façon la plus simple possible.

Ce type de TextBox existe un peu partout dans le système mais n’est pas proposé nativement dans le kit de développement.

WP7-BingSearch

Nous verrons plus tard comment améliorer tout ça 🙂

Pour cela :

Création du composant

  • Créez un projet WP7
  • Ajoutez une classe « TextBoxInfo.cs » et ajoutez le squelette suivant :
/// <summary>
	/// TextBox permettant d'afficher une indication à l'utilisateur
	/// </summary>
	public class TextBoxInfo : TextBox
	{
		#region Constructeurs
		/// <summary>
		/// Initialise une nouvelle instance de la TextBox permettant d'afficher une indication à l'utilisateur
		/// </summary>
		public TextBoxInfo()
		{
			DefaultStyleKey = typeof(TextBoxInfo);
		}
		#endregion
	}
  • Ajoutez un TemplatePart correspondant à l’emplacement que nous utiliserons pour l’indication visuelle
/// <summary>
	/// TextBox permettant d'afficher une indication à l'utilisateur
	/// </summary>
	[TemplatePart(Name = "WatermarkContentElement", Type = typeof(FrameworkElement))]
	public class TextBoxInfo : TextBox
	{
  • Ajoutez une DP et son wrapper permettant de définir le contenu de l’indication visuelle
/// <summary>
	/// TextBox permettant d'afficher une indication à l'utilisateur
	/// </summary>
	[TemplatePart(Name = "WatermarkContentElement", Type = typeof(FrameworkElement))]
	public class TextBoxInfo : TextBox
	{
		#region DPs
		/// <summary>
		/// Définit la DP permettant de mentionner le contenu à afficher pour l'indication dans la TextBox
		/// </summary>
		public static readonly DependencyProperty WatermarkContentProperty = DependencyProperty.Register("WatermarkContent", typeof(Object), typeof(TextBoxInfo), new PropertyMetadata(OnWatermarkPropertyChanged));

		#endregion

		#region Constructeurs
		/// <summary>
		/// Initialise une nouvelle instance de la TextBox permettant d'afficher une indication à l'utilisateur
		/// </summary>
		public TextBoxInfo()
		{
			DefaultStyleKey = typeof(TextBoxInfo);
		}
		#endregion

		#region Propriétées
		/// <summary>
		/// Obtient ou définit l'indication visuelle à afficher
		/// </summary>
		public Object WatermarkContent
		{
			get
			{
				return GetValue(WatermarkContentProperty) as Object;
			}
			set
			{
				SetValue(WatermarkContentProperty, value);
			}
		}
		#endregion

	}
  • Maintenant redéfinissez la méthode OnApplyTemplate appelée avant l’affichage du composant

Nous récupérons le TemplatePart et le gardons en membre privé.

/// <summary>
	/// TextBox permettant d'afficher une indication à l'utilisateur
	/// </summary>
	[TemplatePart(Name = "WatermarkContentElement", Type = typeof(FrameworkElement))]
	public class TextBoxInfo : TextBox
	{
		#region Membres
		private ContentControl _watermarkContent;
		#endregion
		...
		/// <summary>
		/// Appelé juste avant d'être affiché à l'écran
		/// </summary>
		public override void OnApplyTemplate()
		{
			base.OnApplyTemplate();

			_watermarkContent = GetTemplateChild("WatermarkContentElement") as ContentControl;

			if (_watermarkContent != null)
				ComputeWatermarkContentVisibility();
		}
		...
}
  • Pour terminer redéfinissez les méthodes OnGotFocus et OnLostFocus

Nous faisons ici la logique d’affichage et masquage de l’indication visuelle en fonction du texte saisi par l’utilisateur et du Focus.

/// <summary>
	/// TextBox permettant d'afficher une indication à l'utilisateur
	/// </summary>
	[TemplatePart(Name = "WatermarkContentElement", Type = typeof(FrameworkElement))]
	public class TextBoxInfo : TextBox
	{
		#region Membres
		private ContentControl _watermarkContent;
		#endregion

		#region DPs
		/// <summary>
		/// Définit la DP permettant de mentionner le contenu à afficher pour l'indication dans la TextBox
		/// </summary>
		public static readonly DependencyProperty WatermarkContentProperty = DependencyProperty.Register("WatermarkContent", typeof(Object), typeof(TextBoxInfo), new PropertyMetadata(OnWatermarkPropertyChanged));

		#endregion

		#region Constructeurs
		/// <summary>
		/// Initialise une nouvelle instance de la TextBox permettant d'afficher une indication à l'utilisateur
		/// </summary>
		public TextBoxInfo()
		{
			DefaultStyleKey = typeof(TextBoxInfo);
		}
		#endregion

		#region Propriétées
		/// <summary>
		/// Obtient ou définit l'indication visuelle à afficher
		/// </summary>
		public Object WatermarkContent
		{
			get
			{
				return GetValue(WatermarkContentProperty) as Object;
			}
			set
			{
				SetValue(WatermarkContentProperty, value);
			}
		}
		#endregion

		#region Méthodes
		private void ComputeWatermarkContentVisibility()
		{
			if (_watermarkContent != null)
				_watermarkContent.Visibility = String.IsNullOrEmpty(this.Text) ? Visibility.Visible : Visibility.Collapsed;
		}
		#endregion

		#region Handlers
		/// <summary>
		/// Appelé juste avant d'être affiché à l'écran
		/// </summary>
		public override void OnApplyTemplate()
		{
			base.OnApplyTemplate();

			_watermarkContent = GetTemplateChild("WatermarkContentElement") as ContentControl;

			if (_watermarkContent != null)
				ComputeWatermarkContentVisibility();
		}

		/// <summary>
		/// Appelé avant que la TextBox récupère le focus
		/// </summary>
		/// <param name="e">Les données de l'évènement</param>
		protected override void OnGotFocus(RoutedEventArgs e)
		{
			if (_watermarkContent != null)
				_watermarkContent.Visibility = Visibility.Collapsed;

			base.OnGotFocus(e);
		}

		/// <summary>
		/// Appelé avant que la TextBox ne perde le focus
		/// </summary>
		/// <param name="e">Les données de l'évènement</param>
		protected override void OnLostFocus(RoutedEventArgs e)
		{
			if ((_watermarkContent != null) && (String.IsNullOrEmpty(Text)))
				_watermarkContent.Visibility = Visibility.Visible;

			base.OnLostFocus(e);
		}

		private static void OnWatermarkPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
		{
			TextBoxInfo self = sender as TextBoxInfo;

			if ((self != null) && (self._watermarkContent != null))
			{
				self.ComputeWatermarkContentVisibility();
			}
		}
		#endregion
	}

Création du style associé

Nous disposons dont un nouveau ContentControl que nous utiliserons pour afficher l’indication visuelle.

WP7-TextBoxInfo-Watermark

<ControlTemplate x:Key="PhoneDisabledTextBoxTemplate"
					 TargetType="TextBox">
		<ContentControl x:Name="ContentElement"
						BorderThickness="0"
						HorizontalContentAlignment="Stretch"
						Margin="{StaticResource PhoneTextBoxInnerMargin}"
						Padding="{TemplateBinding Padding}"
						VerticalContentAlignment="Stretch" />
	</ControlTemplate>

	<Style  TargetType="Controls:TextBoxInfo">
		<Setter Property="FontFamily"
				Value="{StaticResource PhoneFontFamilyNormal}" />
		<Setter Property="FontSize"
				Value="{StaticResource PhoneFontSizeMediumLarge}" />
		<Setter Property="Background"
				Value="{StaticResource PhoneTextBoxBrush}" />
		<Setter Property="Foreground"
				Value="{StaticResource PhoneTextBoxForegroundBrush}" />
		<Setter Property="BorderBrush"
				Value="{StaticResource PhoneTextBoxBrush}" />
		<Setter Property="SelectionBackground"
				Value="{StaticResource PhoneAccentBrush}" />
		<Setter Property="SelectionForeground"
				Value="{StaticResource PhoneTextBoxSelectionForegroundBrush}" />
		<Setter Property="BorderThickness"
				Value="{StaticResource PhoneBorderThickness}" />
		<Setter Property="Padding"
				Value="2" />
		<Setter Property="Template">
			<Setter.Value>
				<ControlTemplate TargetType="Controls:TextBoxInfo">
					<Grid Background="Transparent">
						<VisualStateManager.VisualStateGroups>
							<VisualStateGroup x:Name="CommonStates">
								<VisualState x:Name="Normal" />
								<VisualState x:Name="MouseOver" />
								<VisualState x:Name="Disabled">
									<Storyboard>
										<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility"
																	   Storyboard.TargetName="EnabledBorder">
											<DiscreteObjectKeyFrame KeyTime="0">
												<DiscreteObjectKeyFrame.Value>
													<Visibility>Collapsed</Visibility>
												</DiscreteObjectKeyFrame.Value>
											</DiscreteObjectKeyFrame>
										</ObjectAnimationUsingKeyFrames>
										<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility"
																	   Storyboard.TargetName="DisabledOrReadonlyBorder">
											<DiscreteObjectKeyFrame KeyTime="0">
												<DiscreteObjectKeyFrame.Value>
													<Visibility>Visible</Visibility>
												</DiscreteObjectKeyFrame.Value>
											</DiscreteObjectKeyFrame>
										</ObjectAnimationUsingKeyFrames>
									</Storyboard>
								</VisualState>
								<VisualState x:Name="ReadOnly">
									<Storyboard>
										<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility"
																	   Storyboard.TargetName="EnabledBorder">
											<DiscreteObjectKeyFrame KeyTime="0">
												<DiscreteObjectKeyFrame.Value>
													<Visibility>Collapsed</Visibility>
												</DiscreteObjectKeyFrame.Value>
											</DiscreteObjectKeyFrame>
										</ObjectAnimationUsingKeyFrames>
										<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility"
																	   Storyboard.TargetName="DisabledOrReadonlyBorder">
											<DiscreteObjectKeyFrame KeyTime="0">
												<DiscreteObjectKeyFrame.Value>
													<Visibility>Visible</Visibility>
												</DiscreteObjectKeyFrame.Value>
											</DiscreteObjectKeyFrame>
										</ObjectAnimationUsingKeyFrames>
										<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background"
																	   Storyboard.TargetName="DisabledOrReadonlyBorder">
											<DiscreteObjectKeyFrame KeyTime="0"
																	Value="{StaticResource PhoneTextBoxBrush}" />
										</ObjectAnimationUsingKeyFrames>
										<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush"
																	   Storyboard.TargetName="DisabledOrReadonlyBorder">
											<DiscreteObjectKeyFrame KeyTime="0"
																	Value="{StaticResource PhoneTextBoxBrush}" />
										</ObjectAnimationUsingKeyFrames>
										<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground"
																	   Storyboard.TargetName="DisabledOrReadonlyContent">
											<DiscreteObjectKeyFrame KeyTime="0"
																	Value="{StaticResource PhoneTextBoxReadOnlyBrush}" />
										</ObjectAnimationUsingKeyFrames>
									</Storyboard>
								</VisualState>
							</VisualStateGroup>
							<VisualStateGroup x:Name="FocusStates">
								<VisualState x:Name="Focused">
									<Storyboard>
										<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background"
																	   Storyboard.TargetName="EnabledBorder">
											<DiscreteObjectKeyFrame KeyTime="0"
																	Value="{StaticResource PhoneTextBoxEditBackgroundBrush}" />
										</ObjectAnimationUsingKeyFrames>
										<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush"
																	   Storyboard.TargetName="EnabledBorder">
											<DiscreteObjectKeyFrame KeyTime="0"
																	Value="{StaticResource PhoneTextBoxEditBorderBrush}" />
										</ObjectAnimationUsingKeyFrames>
									</Storyboard>
								</VisualState>
								<VisualState x:Name="Unfocused" />

							</VisualStateGroup>
						</VisualStateManager.VisualStateGroups>
						<Border x:Name="EnabledBorder"
								BorderBrush="{TemplateBinding BorderBrush}"
								BorderThickness="{TemplateBinding BorderThickness}"
								Background="{TemplateBinding Background}"
								Margin="{StaticResource PhoneTouchTargetOverhang}">
							<Grid>

								<ContentControl x:Name="WatermarkContentElement"
												IsHitTestVisible="False"
												Background="Transparent"
												Padding="{TemplateBinding Padding}"
												Content="{TemplateBinding WatermarkContent}"
												HorizontalAlignment="Left"
												Opacity="0.5" />

								<ContentControl x:Name="ContentElement"
												BorderThickness="0"
												HorizontalContentAlignment="Stretch"
												Margin="{StaticResource PhoneTextBoxInnerMargin}"
												Padding="{TemplateBinding Padding}"
												VerticalContentAlignment="Stretch" />
							</Grid>
						</Border>
						<Border x:Name="DisabledOrReadonlyBorder"
								BorderBrush="{StaticResource PhoneDisabledBrush}"
								BorderThickness="{TemplateBinding BorderThickness}"
								Background="Transparent"
								Margin="{StaticResource PhoneTouchTargetOverhang}"
								Visibility="Collapsed">
							<TextBox x:Name="DisabledOrReadonlyContent"
									 Background="Transparent"
									 Foreground="{StaticResource PhoneDisabledBrush}"
									 FontWeight="{TemplateBinding FontWeight}"
									 FontStyle="{TemplateBinding FontStyle}"
									 FontSize="{TemplateBinding FontSize}"
									 FontFamily="{TemplateBinding FontFamily}"
									 IsReadOnly="True"
									 SelectionForeground="{TemplateBinding SelectionForeground}"
									 SelectionBackground="{TemplateBinding SelectionBackground}"
									 TextAlignment="{TemplateBinding TextAlignment}"
									 TextWrapping="{TemplateBinding TextWrapping}"
									 Text="{TemplateBinding Text}"
									 Template="{StaticResource PhoneDisabledTextBoxTemplate}" />
						</Border>
					</Grid>
				</ControlTemplate>
			</Setter.Value>
		</Setter>
	</Style>

Utilisation du composant

<Controls:TextBoxInfo WatermarkContent="Rechercher..." />

Rendu

WP7-TextBoxInfo-Watermark-Rendu

Sympa non ? 🙂

[Promo] : Excellent blog Android / C# / Java

17 décembre 2011 1 commentaire

android_logoBonjour à tous, un petit article afin de vous présenter un blog très intéressant sur les technologies Android, Java et C#.

Vous y trouverez notamment une grande série d’articles sur le développement mobile Android ! Alors si vous souhaitez vous mettre à développer (ou vous perfectionner) sur la plateforme Android, je vous recommande ce blog réalisé par Pierre-Emmanuel Mercier 🙂

Bonne programmation !

Catégories :Android