Archive

Archive for the ‘Silverlight’ Category

[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

[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 : ,

[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 ? 🙂

[WP7] : Silverlight Control Toolkit pour WP7.1 – Novembre

Une nouvelle version du Silverlight Control Toolkit pour Windows Phone 7.1 vient de sortir.

WP7 - silverlight toolkit - november

C’est par ici :

What’s new

  • ListPicker once again works in a ScrollViewer
  • LongListSelector bug fixes around OutOfRange exceptions, wrong ordering of items, grouping issues, and scrolling events. ItemTuple is now refactored to be the public type LongListSelectorItem to provide users better access to the values in selection changed handlers.
  • PerformanceProgressBar binding fix for IsIndeterminate (item 9767 and others)
  • There is no longer a GestureListener dependency with the ContextMenu, WrapPanel, and ListPicker
  • The GestureListener should be considered deprecated for all Windows Phone 7.1 SDK development. There is no direct replacement at this time, though the platform now supports events such as Tap right on visual elements.

Other changes

  • Updates the ExpanderView sample so that each individual item has its own tilt effect.
  • Fixes PhoneTextBox bugs 9342 and 9345
  • PhoneTextBox hides actionitem when empty
  • ListPicker can be in horizontally scrollable views.
  • ListPicker now only supports Tap for activation (before it supported any touch that began in bounds and stayed in bounds)
  • The LongListSelector’s Background color now is used for the picker grid to enable better app/brand styling
  • LongListSelector state name correction
  • Comments added to clarify that ListPicker does not support UIElements directly by design since the framework only permits one instance of a UI Element in the tree at a time
  • ExpanderView visual glitch fixed (9525)
  • Additional null checks in ContextMenu visual state change methods
  • ListPicker SelectedItems is now settable
  • Small fixes to ToggleSwitch
  • A startup crash correction in the gesture listener.
  • The ExpanderView sample is documented better
  • LockablePivot’s IsLocked property is now a dependency property
  • RelativeTimerConverter fixes a UTC bug and no longer throws on future dates
  • Fixes some reported issues with VB.NET samples
  • Fixed a ToggleSwitchButton reanimation issue.
  • Owner is a public property now on ContextMenu
  • Handle listpicker selected item with a null items
  • Fixes sample issues when building.
  • Fixes build warnings.
Catégories :Silverlight, Windows Phone 7

[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 🙂

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

[SL-SPCOM] : SP2010 Client Object Model – Part 1

Une nouveauté intéressante pour la communauté Silverlight est apparue dans SharePoint 2010. Il est désormais possible, grâce au Client Objet Model, de réaliser des applications interagissant avec SharePoint 2010 sans avoir à réaliser du code personnalisé sur l’environnement SharePoint.

Grâce au Client Object Model nous pouvons à présent réaliser simplement des applications Silverlight ou ECMAScript (JavaScript) accédant à SharePoint sans avoir à développer quoi que ce soit sur l’environnement SharePoint 2010.

Dans SharePoint 2007, nous devions utiliser des WebServices pour réaliser ces opérations. Ce qui avait donc un impact sur les délais de développement d’une application cliente.

Les références nécessaires

Pour un projet Silverlight

Vous devez référencer l’assembly « Microsoft.SharePoint.Client.Silverlight.dll » et « Microsoft.SharePoint.Client.Silverlight.Runtime.dll » qui se trouve dans l’installation SharePoint 2010 à l’emplacement suivant : « C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\ClientBin\ »

Pour un projet .net classique

Vous devez référencer l’assembly « Microsoft.SharePoint.Client.dll » et « Microsoft.SharePoint.Client.Runtime.dll » qui se trouve dans l’installation SharePoint 2010 à l’emplacement suivant : « C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\ISAPI\ »

L’API

Le Client Object Model est un « mapping » des objets présents sur le modèle objet Sharepoint ainsi vous retrouverez des noms familiers pour un développeur SharePoint :

  • Site -> SPSite
  • Web –> SPWeb
  • ClientContext -> SPContext
  • User -> SPUser
  • List -> SPList
  • ListItem -> SPListItem
  • Field  -> SPField
  • File -> SPFile
  • Folder -> SPFolder

Utilisation

Afin de voir comment utiliser cette librairie nous allons en guise d’exemple tenter de récupérer la liste des « Listes SharePoint » disponibles.

Récupération du contexte / création d’une connexion

 using (ClientContext clientContext = new ClientContext("http://yoursharepointweburl"))
            {
               //actions TODO
            }

Initialisation de la requête

Pour cela il faut tout d’abord utiliser « clientContext.LoadQuery » qui va se charger d’empiler une action à réaliser.

ListCollection listCollections = clientContext.Web.Lists;
clientContext.LoadQuery(listCollections);

A ce stade vous ne pouvez toujours pas utiliser la variable listCollections car elle n’est toujours pas initialisée !

Exécution de la requête

Pour cela il faut appeler « clientContext.ExecuteQuery(); » qui va réaliser l’appel au serveur. Il est donc possible d’empiler plusieurs actions et de faire qu’un seul appel. Limitant ainsi les appel couteux Client Serveur…

    clientContext.ExecuteQuery();

A ce moment le serveur SharePoint est appelée et une réponse JSon est reçue contenant la collection des Listes SharePoint demandées :
[
{
« SchemaVersion »: »14.0.0.0″, »LibraryVersion »: »14.0.4762.1000″, »ErrorInfo »:null
},16,{
« IsNull »:false
},18,{
« IsNull »:false
},20,{
« IsNull »:false
},21,{
« _ObjectType_ »: »SP.ListCollection », »_Child_Items_ »:[
{
« _ObjectType_ »: »SP.List », »_ObjectIdentity_ »: »740c6a0b-85e2-48a0-a494-e0f1759d4aa7:web:5db0d1d5-c41a-43ec-82c3-b694288a3ef9:list:7461b3be-a298-477d-970b-74e07c053a32″, »_ObjectVersion_ »: »0″, »ParentWebUrl »: »\u002f », »HasExternalDataSource »:false, »Created »: »\/Date(1303826931000)\/ », »LastItemModifiedDate »: »\/Date(1303995918000)\/ », »LastItemDeletedDate »: »\/Date(1303826931000)\/ », »Id »: »\/Guid(7461b3be-a298-477d-970b-74e07c053a32)\/ », »Description »: »Cette liste vous permet de prendre connaissance des \u00e9v\u00e9nements \u00e0 venir, des changements d\u2019\u00e9tat ou d\u2019autres informations concernant votre \u00e9quipe. », »Title »: »Annonces », »Direction »: »none », »BaseType »:0, »ImageUrl »: »\u002f_layouts\u002fimages\u002fitann.png », »ItemCount »:2, »BaseTemplate »:104, »DefaultContentApprovalWorkflowId »: »\/Guid(00000000-0000-0000-0000-000000000000)\/ », »TemplateFeatureId »: »\/Guid(00bfea71-d1ce-42de-9c63-a44004ce0104)\/ », »DefaultViewUrl »: »\u002fLists\u002fAnnonces\u002fAllItems.aspx », »DefaultEditFormUrl »: »\u002fLists\u002fAnnonces\u002fEditForm.aspx », »DefaultNewFormUrl »: »\u002fLists\u002fAnnonces\u002fNewForm.aspx », »DefaultDisplayFormUrl »: »\u002fLists\u002fAnnonces\u002fDispForm.aspx », »EnableAttachments »:true, »ServerTemplateCanCreateFolders »:true, »EnableFolderCreation »:false, »EnableModeration »:false, »EnableVersioning »:false, »ForceCheckout »:false, »EnableMinorVersions »:false, »DraftVersionVisibility »:0, »Hidden »:false, »IsApplicationList »:false, »IsCatalog »:false, »AllowContentTypes »:true, »DocumentTemplateUrl »:null, »ContentTypesEnabled »:false, »MultipleDataList »:false, »NoCrawl »:false
},{
« _ObjectType_ »: »SP.List », »_ObjectIdentity_ »: »740c6a0b-85e2-48a0-a494-e0f1759d4aa7:web:5db0d1d5-c41a-43ec-82c3-b694288a3ef9:list:4a1affe4-2721-4321-bf20-eab8ca008942″, »_ObjectVersion_ »: »0″, »ParentWebUrl »: »\u002f », »HasExternalDataSource »:false, »Created »: »\/Date(1303826923000)\/ », »LastItemModifiedDate »: »\/Date(1303826923000)\/ », »LastItemDeletedDate »: »\/Date(1303826923000)\/ », »Id »: »\/Guid(4a1affe4-2721-4321-bf20-eab8ca008942)\/ », »Description »: »Utilisez la biblioth\u00e8que de style pour stocker des feuilles de style telles que des fichiers CSS ou XSL. Les feuilles de style de cette galerie peuvent \u00eatre utilis\u00e9es par ce site et tous ses sous-sites. », »Title »: »Biblioth\u00e8que de styles », »Direction »: »none », »BaseType »:1, »ImageUrl »: »\u002f_layouts\u002fimages\u002fitdl.png », »ItemCount »:0, »BaseTemplate »:101, »DefaultContentApprovalWorkflowId »: »\/Guid(00000000-0000-0000-0000-000000000000)\/ », »TemplateFeatureId »: »\/Guid(00bfea71-e717-4e80-aa17-d0c71b360101)\/ », »DefaultViewUrl »: »\u002fStyle Library\u002fForms\u002fAllItems.aspx », »DefaultEditFormUrl »: »\u002fStyle Library\u002fForms\u002fEditForm.aspx », »DefaultNewFormUrl »: »\u002fStyle Library\u002fForms\u002fUpload.aspx », »DefaultDisplayFormUrl »: »\u002fStyle Library\u002fForms\u002fDispForm.aspx », »EnableAttachments »:false, »ServerTemplateCanCreateFolders »:true, »EnableFolderCreation »:true, »EnableModeration »:false, »EnableVersioning »:false, »ForceCheckout »:false, »EnableMinorVersions »:false, »DraftVersionVisibility »:0, »Hidden »:false, »IsApplicationList »:false, »IsCatalog »:true, »AllowContentTypes »:true, »DocumentTemplateUrl »:null, »ContentTypesEnabled »:false, »MultipleDataList »:false, »NoCrawl »:false
},

{
« _ObjectType_ »: »SP.List », »_ObjectIdentity_ »: »740c6a0b-85e2-48a0-a494-e0f1759d4aa7:web:5db0d1d5-c41a-43ec-82c3-b694288a3ef9:list:08a34d3e-9336-4124-b6a0-d8e7ce442192″, »_ObjectVersion_ »: »6″, »ParentWebUrl »: »\u002f », »HasExternalDataSource »:false, »Created »: »\/Date(1303828530000)\/ », »LastItemModifiedDate »: »\/Date(1303828853000)\/ », »LastItemDeletedDate »: »\/Date(1303828530000)\/ », »Id »: »\/Guid(08a34d3e-9336-4124-b6a0-d8e7ce442192)\/ », »Description »: » », »Title »: »Utilisateurs », »Direction »: »none », »BaseType »:0, »ImageUrl »: »\u002f_layouts\u002fimages\u002fitgen.png », »ItemCount »:2, »BaseTemplate »:100, »DefaultContentApprovalWorkflowId »: »\/Guid(00000000-0000-0000-0000-000000000000)\/ », »TemplateFeatureId »: »\/Guid(00bfea71-de22-43b2-a848-c05709900100)\/ », »DefaultViewUrl »: »\u002fLists\u002fUtilisateurs\u002fAllItems.aspx », »DefaultEditFormUrl »: »\u002fLists\u002fUtilisateurs\u002fEditForm.aspx », »DefaultNewFormUrl »: »\u002fLists\u002fUtilisateurs\u002fNewForm.aspx », »DefaultDisplayFormUrl »: »\u002fLists\u002fUtilisateurs\u002fDispForm.aspx », »EnableAttachments »:true, »ServerTemplateCanCreateFolders »:true, »EnableFolderCreation »:false, »EnableModeration »:false, »EnableVersioning »:false, »ForceCheckout »:false, »EnableMinorVersions »:false, »DraftVersionVisibility »:0, »Hidden »:false, »IsApplicationList »:false, »IsCatalog »:false, »AllowContentTypes »:true, »DocumentTemplateUrl »:null, »ContentTypesEnabled »:false, »MultipleDataList »:false, »NoCrawl »:false
},{
« _ObjectType_ »: »SP.List », »_ObjectIdentity_ »: »740c6a0b-85e2-48a0-a494-e0f1759d4aa7:web:5db0d1d5-c41a-43ec-82c3-b694288a3ef9:list:e278088c-0c52-40dd-9b32-1719cef6c0f3″, »_ObjectVersion_ »: »0″, »ParentWebUrl »: »\u002f », »HasExternalDataSource »:false, »Created »: »\/Date(1304005536000)\/ », »LastItemModifiedDate »: »\/Date(1304005536000)\/ », »LastItemDeletedDate »: »\/Date(1304005536000)\/ », »Id »: »\/Guid(e278088c-0c52-40dd-9b32-1719cef6c0f3)\/ », »Description »: »description de la voiture », »Title »: »voiture », »Direction »: »none », »BaseType »:1, »ImageUrl »: »\u002f_layouts\u002fimages\u002fitwp.png », »ItemCount »:0, »BaseTemplate »:119, »DefaultContentApprovalWorkflowId »: »\/Guid(00000000-0000-0000-0000-000000000000)\/ », »TemplateFeatureId »: »\/Guid(00bfea71-c796-4402-9f2f-0eb9a6e71b18)\/ », »DefaultViewUrl »: »\u002fvoiture\u002fForms\u002fAllPages.aspx », »DefaultEditFormUrl »: »\u002fvoiture\u002fForms\u002fEditForm.aspx », »DefaultNewFormUrl »: »\u002fvoiture\u002fForms\u002fUpload.aspx », »DefaultDisplayFormUrl »: »\u002fvoiture\u002fForms\u002fDispForm.aspx », »EnableAttachments »:false, »ServerTemplateCanCreateFolders »:true, »EnableFolderCreation »:false, »EnableModeration »:false, »EnableVersioning »:true, »ForceCheckout »:false, »EnableMinorVersions »:false, »DraftVersionVisibility »:0, »Hidden »:false, »IsApplicationList »:true, »IsCatalog »:false, »AllowContentTypes »:true, »DocumentTemplateUrl »:null, »ContentTypesEnabled »:false, »MultipleDataList »:false, »NoCrawl »:false
}
]
}
]

Comme on peut le voir nous recevons beaucoup d’informations, ce qui n’est peut être pas utilise tout le temps. Parfois nous n’avons besoin que de 2 ou 3 informations, il serait donc judicieux de ne renvoyer que ce dont on a vraiment besoin pour améliorer les performances de l’application.

Comment récupérer les listes avec uniquement certaines données ?

Pour faire cela rien de plus simple car la librairie est très modulable.
Il suffit de changer l’appel à la méthode Load vu ci-dessus par l’expression suivante utilisant des lambda Linq.
Nous allons par exemple demander à ne récupérer que les propriétées Title, TemplateFeatureId et ImageUrl de chaques listes

 clientContext.Load(listCollections, (lists => lists.Include(list => list.Title, list => list.TemplateFeatureId, list => list.ImageUrl)));

Nous obtenons une réponse JSon beaucoup plus « light » et donc beaucoup plus petite à transférer sur un réseau informatique.

[
{
« SchemaVersion »: »14.0.0.0″, »LibraryVersion »: »14.0.4762.1000″, »ErrorInfo »:null
},90,{
« IsNull »:false
},92,{
« IsNull »:false
},94,{
« IsNull »:false
},95,{
« _ObjectType_ »: »SP.ListCollection », »_Child_Items_ »:[
{
« _ObjectType_ »: »SP.List », »_ObjectIdentity_ »: »740c6a0b-85e2-48a0-a494-e0f1759d4aa7:web:5db0d1d5-c41a-43ec-82c3-b694288a3ef9:list:7461b3be-a298-477d-970b-74e07c053a32″, »_ObjectVersion_ »: »0″, »Title »: »Annonces », »TemplateFeatureId »: »\/Guid(00bfea71-d1ce-42de-9c63-a44004ce0104)\/ », »ImageUrl »: »\u002f_layouts\u002fimages\u002fitann.png »
},{
« _ObjectType_ »: »SP.List », »_ObjectIdentity_ »: »740c6a0b-85e2-48a0-a494-e0f1759d4aa7:web:5db0d1d5-c41a-43ec-82c3-b694288a3ef9:list:4a1affe4-2721-4321-bf20-eab8ca008942″, »_ObjectVersion_ »: »0″, »Title »: »Biblioth\u00e8que de styles », »TemplateFeatureId »: »\/Guid(00bfea71-e717-4e80-aa17-d0c71b360101)\/ », »ImageUrl »: »\u002f_layouts\u002fimages\u002fitdl.png »
},

{
« _ObjectType_ »: »SP.List », »_ObjectIdentity_ »: »740c6a0b-85e2-48a0-a494-e0f1759d4aa7:web:5db0d1d5-c41a-43ec-82c3-b694288a3ef9:list:08a34d3e-9336-4124-b6a0-d8e7ce442192″, »_ObjectVersion_ »: »6″, »Title »: »Utilisateurs », »TemplateFeatureId »: »\/Guid(00bfea71-de22-43b2-a848-c05709900100)\/ », »ImageUrl »: »\u002f_layouts\u002fimages\u002fitgen.png »
},{
« _ObjectType_ »: »SP.List », »_ObjectIdentity_ »: »740c6a0b-85e2-48a0-a494-e0f1759d4aa7:web:5db0d1d5-c41a-43ec-82c3-b694288a3ef9:list:e278088c-0c52-40dd-9b32-1719cef6c0f3″, »_ObjectVersion_ »: »0″, »Title »: »voiture », »TemplateFeatureId »: »\/Guid(00bfea71-c796-4402-9f2f-0eb9a6e71b18)\/ », »ImageUrl »: »\u002f_layouts\u002fimages\u002fitwp.png »
}
]
}
]

Soit une réponse de 8 109 bytes contre de 35 524 bytes pour la requête initiale !

Comment factoriser cela sous forme de méthodes ?

Méthodes pour récupérer les listes
using System;
using Microsoft.SharePoint.Client;
using File = Microsoft.SharePoint.Client.File;
using System.Linq.Expressions;
using System.Linq;
using System.Collections.Generic;
using System.Windows.Threading;
using System.Threading;
using System.Text;

namespace SliverlightSPTests
{
    ///
<summary> /// Classe permettant de simplifier les accès à SharePoint via Silverlight
 /// </summary>
    public class SharePointTools
    {
        #region Membres
          private String _webFullUrl = String.Empty;
        #endregion

        #region Ctors
        ///
<summary> /// Créé une instance de la classe permettant de simplifier les accès à SharePoint via Silverlight
 /// </summary>
        ///Url du site sur lequel les requetes vont s'effectuer
        public SharePointTools(String webUrl)
        {
            _webFullUrl = webUrl;
           }
        #endregion

        #region Méthodes

 ///
<summary> /// Permet de récupérer les listes (avec toutes les propriétés) du site actuel
 /// </summary>
        /// Collection des listes du site
        public ListCollection GetAllList()
        {
            ListCollection listCollections = null;

            using (ClientContext clientContext = new ClientContext(_webFullUrl))
            {
                listCollections = clientContext.Web.Lists;

                clientContext.Load(listCollections);
                clientContext.ExecuteQuery();
            }

            return listCollections;
        }

        ///
<summary> /// Permet de récupérer les listes (avec uniquement les propriétés spécifiées) du site actuel
 /// </summary>
        ///Filtres d'inclusion à appliquer sur la requete
        /// Collection des listes du site
        public ListCollection GetAllListWithSpecificProperties(Expression> retrievals)
        {
            ListCollection listCollections = null;

            using (ClientContext clientContext = new ClientContext(_webFullUrl))
            {
                listCollections = clientContext.Web.Lists;

                clientContext.Load(listCollections, retrievals);
                clientContext.ExecuteQuery();
            }

            return listCollections;
        }
#endregion
}
Comment l’appeler ?

Le Client Object Model Silverlight n’accepte pas les appels synchrones autrement dit non exécutés dans une autre Thread que celui de l’UI.

SharePointTools sptools = new SharePointTools("http://yoursharepointweburl");
				ThreadPool.QueueUserWorkItem(new WaitCallback((o) =>
				{
					ListCollection lists = sptools.GetAllList();
                    //ou : IEnumerable lists = sptools.GetAllListWithSpecificProperties((l => l.Include(list => list.Title, list => list.TemplateFeatureId, list => list.ImageUrl)));

					Dispatcher.BeginInvoke(() =>
					{
						Lists.ItemsSource = lists;
					});
				}));

Résultat

Il est donc facile de réaliser des WebPart dynamiques en Silverlight avec un minimum d’effort !

SP2010-COM-GetList

Prochainement

Nous verrons plus en détail comment intéragir avec les Listes SharePoint et comment simplifier les appels vers la Client Object Library