Skip to main content

Le Blog de Georges Legros

Go Search
Home
  

Moi
WCF : Problème de buffer

Il arrive parfois qu’avec WCF on ai envie de s’arracher les cheveux… A plus forte raison si vous l’utilisez avec une application Silverlight.

En effet, les messages d’erreur sont la plupart du temps complètement  incompréhensibles et sans rapport avec votre problème (ex : 404 Not Found pour tout et pour rien…)

Le problème qui m’occupe actuellement est de faire transiter des fichier entre l’application (Silverlight donc) et le serveur WCF :

Alors que tout fonctionne dans votre environnement de test (presque identique à votre environnement de prod) une fois dans votre application, plus rien ne fonctionne, malgré les réglage faits au niveau de la taille du buffer alloué pour WCF:

<basicHttpBinding>
  <binding name="AnalysisServiceBinding" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647">
    <readerQuotas maxArrayLength="2147483647" maxStringContentLength="2147483647"/>
  </binding>
</basicHttpBinding>

Et ici aussi, erreur 404.

Après plusieurs test, il apparait que des fichiers de petites tailles passent alors que certains plus gros sont bloqué… Etrange, nous venons de régler le problème.

C’est là qu’une analyse de l’architecture de mon projet m’a fait découvrir l’erreur.

Au fait, notre service WCF est configuré pour être hosté dans un site web asp.NET et de ce fait, il y a un deuxième buffer à augmenter.

<httpRuntime maxRequestLength=”6000”/>
Problème règlé !
MCTS Windows Communication Foundation

Après le WPF c'était au tour de WCF !!!

MCTS WCF

 

Prochaine étape ADO.NET 3.5 (en bonne voie d'ailleur ;-))

 

 

Le logo de droite a donc été mis à jour !

Une horloge WPF

En regardant l' horloge des gadget Vista, j'ai pensé qu'il pourrait être intéressant de refaire cette dernière en WPF.

A coup de Path et d'Ellipses, le corps de cette dernière fût vite construit (fichiers XAML et CS)

image

Jusqu'ici tout va bien mais les choses se corsent lorsqu'on désire lier l'angle de rotation des aiguilles à l'heure actuelle. Ici deux problème se posent :

  1. L'objet DateTime n'implémente pas IValueConverter, on peut donc récupérer l'heure au load de l'objet mais lorsqu'elle changera, on ne sera pas averti..
  2. Il faut faire la relation entre l'heure et l'angle de rotation des aiguille (un peu de math...)

On commencera donc par écrire la classe (appelée ici TimeDelivery) comme ceci (Télécharger le fichier) :

    internal class TimeDelivery : INotifyPropertyChanged

    {

        private Timer timer;

        private DateTime dateTime = DateTime.Now;

        private long refreshPeriod = 1000;

        public DateTime DateTime

        {

            get { return dateTime; }

            set

            {

                if (dateTime != value)

                {

                    dateTime = value;

                    OnPropertyChanged("DateTime");

                }

            }

        }

        public long RefreshPeriod

        {

            get { return refreshPeriod; }

            set

            {

                if (refreshPeriod != value)

                {

                    refreshPeriod = value;

                    OnPropertyChanged("RefreshPeriod");

                }

            }

        }

        public TimeDelivery()

        {

            timer = new Timer(new TimerCallback(DateTimeCallBack), null, 0, this.RefreshPeriod);

        }

        private void DateTimeCallBack(object state)

        {

            this.DateTime = DateTime.Now;

        }

        private void OnPropertyChanged(string name)

        {

            if (PropertyChanged != null)

                PropertyChanged(this, new PropertyChangedEventArgs(name));

        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

    }

Maintenant que 'on peut récupérer l'heure courrante, il faut calculer l'angle des aiguilles en fonction de l'heure. Ici j'ai choisi d'écrire des converter, en voici un (le fichier complet) :

    internal class HourToAngle : IValueConverter

    {

        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)

        {

            DateTime time = System.Convert.ToDateTime(value);

            double Angle = time.Hour * 30;

            Angle += 12 * time.Minute / 60;

            return Angle;

        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)

        {

            // Not required.

            return null;

        }

        #endregion

    }

Voila donc notre horloge fonctionnelle. Ce n'est peut-être pas la meilleure technique mais elle a l'avantage de fonctionner.

MCTS Windows Presentation Foundation

J'ai le plaisir de vous annoncer que depuis fin août je suis MCTS .NET Framework 3.5, Windows Presentation Foundation

 

MCTS(rgb)_1098 

 

J'en profite donc pour rajouter le logo complet à droite ...

Un contrôle de défilement automatique

En html il existe un contrôle permettant de faire défiler du texte automatiquement, le "Marquee"

Exemple de Marquee

Je me suis donc dit qu'il serait peut-être intéressant de passer ce concept dans un environnement WPF.

Afin de créer un contrôle réutilisable, je vais ici présenter un CustomControl complet et non juste un simple style. Ce dernier dérivera de ContentControl afin de pouvoir faire défiler n'importe quel élément.

Commençons tout d'abord par le style:

   <Style TargetType="{x:Type local:Marquee}">
       <Setter Property="Template">
           <Setter.Value>
               <ControlTemplate TargetType="{x:Type local:Marquee}">
                   <Canvas ClipToBounds="True">
                       <ContentPresenter x:Name="PART_Content"/>
                   </Canvas>
               </ControlTemplate>
           </Setter.Value>
       </Setter>
   </Style>

Notre nouveau composant étant un ContentControl, il n'est pas étonnant de retrouver un ContentPresenter. Notez également la présence du tag ClipToBounds dans le Canvas, celui-ci a pour objectif de cacher les éléments qui ne sont pas dans la partie "visible" du Canvas, autrement dit, lorsqu'un item sort du rectangle visible du panel, on ne peut plus le voir.

Ici, rien de très compliqué, je me suis évidement limité au strict nécessaire, avec un peu de style il sera possible de faire des afficheurs beaucoup plus élégant.

Au niveau du code, il n'y a rien d'étonnant. Je choisis de donner la possibilité aux utilisateur de régler la vitesse de défilement et on retrouve également le code nécessaire à l'animation :

   public class Marquee : ContentControl
   {
       FrameworkElement _contentPresenter;
       static Marquee()
       {
           DefaultStyleKeyProperty.OverrideMetadata(typeof(Marquee), new FrameworkPropertyMetadata(typeof(Marquee)));

       }

       public Marquee()
       {
           this.Loaded += new RoutedEventHandler(Marquee_Loaded);
       }

       void Marquee_Loaded(object sender, RoutedEventArgs e)
       {
           Animate();
       }

       public override void OnApplyTemplate()
       {
           _contentPresenter = Template.FindName("PART_Content", this) as FrameworkElement;
       }

       public Duration MarqueeDuration
       {
           get { return (Duration)GetValue(MarqueeDurationProperty); }
           set { SetValue(MarqueeDurationProperty, value); }
       }

       public static readonly DependencyProperty MarqueeDurationProperty =
           DependencyProperty.Register("MarqueeDuration", typeof(Duration), typeof(Marquee), new UIPropertyMetadata(new Duration(new TimeSpan(0))));


       DoubleAnimation _doubleAnimation = new DoubleAnimation();
       Storyboard _storyBoard = new Storyboard();
       private void Animate()
       {
           if (IsLoaded)
           {
               _doubleAnimation.From = this.ActualWidth;
               _doubleAnimation.To = -_contentPresenter.ActualWidth;
               _doubleAnimation.RepeatBehavior = RepeatBehavior.Forever;
               _doubleAnimation.Duration = MarqueeDuration;
               Storyboard.SetTargetProperty(_doubleAnimation, new PropertyPath("(Canvas.Left)"));
               _storyBoard.Children.Add(_doubleAnimation);
               _storyBoard.Begin(_contentPresenter, true);
           }
       }
   }

Il est aussi possible de mettre le code relatif à l'animation dans le style.

Un contrôle de réflexion réutilisable

L'autre jour j'ai eu besoin de faire un peu de réflexion. La technique alors utilisée fonctionnait mais n'était pas réutilisable. J'ai donc décidé d'imaginer une solution plus "propre".

J'ai choisi ici de ne pas créer un contrôle mais bien un template pour un ContentControl.

L'astuce consiste à créer une Grid pourvue de 2 lignes. Dans la première on dépose le ContentPresenter et on lui demande de s'aligner au milieu et en bas. Dans la deuxième on ajoute un Rectangle aligné au milieu et en haut. De cette façon, les deux éléments sont l'un contre l'autre.

Dans les ressources de la Grid, il suffit d'ajouter une VisualBrush provenant du ContentPresenter.

On applique ensuite cette Brush au rectangle et on règle l'OpacityMask en fonction du dégradé voulu.

Resta alors à retourner le rectangle avec le ScaleY à -1 et à binder sa largeur et sa hauteur avec les propriétés ActualWidth et ActualHeight du ContentPresenter.

Voici ce que ça peut donner avec par exemple une image :

ReflectorWithImage

Un TextBlock :

ReflectorWithTextBlock

 

Il y a sûrement moyen de faire mieux mais pour une simple réflexion, ça conviendra très bien !

Voici le style : ICI

Interopérabilité entre les WinForm et WPF

Il y a de cela quelque semaines, un collègue me demandait si il était possible d'inclure  un contrôle WPF dans une application WinForm. après quelques recherches, je suis tombé sur une réponse plutôt satisfaisante.

Pour ceux qui serait intéressé par l'opération contraire, je vais également rappeler comment procéder :

A. Mettre un contrôle WinForm dans une application WPF 

1. Ajouter la références à System.Windows.Forms afin d’accéder aux contrôles Winform

2. Ajouter la références à System.Windows.Forms.Integration afin de récupérer le contrôle WindowsFormsHost (le container dans lequel on placera le contrôle WinForm)

3. Dans le fichier XAML où vous désirez intégrer le contrôle WinForm, ajouter les deux namespaces suivants comme ceci :

xmlns:WindowsFormIntegration="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
xmlns:WinForm="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"

  4. à l'endroit où vous voulez placer votre contrôle WinForm, ajouter un WindowsFormHost dans lequel vous pourrez alors ajouter le contrôle désiré comme ceci :

<WindowsFormIntegration:WindowsFormsHost Grid.Row="1" Height="32" Width="200">
    <WinForm:DateTimePicker />
</WindowsFormIntegration:WindowsFormsHost>

Le résultat pour mon exemple est le suivant :

WinformInWPF

Normalement cela devrait fonctionner de la même manière avec un UserControl

 

 

B. Mettre un contrôle WPF dans une application WinForm

1. Ajouter les références aux assembly de WPF, à savoir PresentationCore, PresentationFramework et UIAutomationProvider

2. Dans le design de votre application, ajouter des panels (ou un autre container, ça devrait marcher) aux endroits ou vous voulez positionner vos contrôles WPF

3. Dans le FormLoad, ajouter le code suivant :

System.Windows.Controls.InkCanvas canvas = new System.Windows.Controls.InkCanvas();
ElementHost host = new ElementHost();
host.Child = canvas ;
host.Dock = DockStyle.Fill;
this.panel.Controls.Add(host);

Ici aussi, cela fonctionne de la même manière pour les UserControls. Voici le résultat de mon applic de démo (j'ai dessiné dans le InkCanvas pour que ce soit plus visuel) :

WPFInWindowsForm

 

Voici donc mon premier article terminé, j'espère qu'il vous sera utile !

 

Projet de démo ici

 Présentation

Employé chez Vision EZOS depuis Juillet 2008, je suis passionné de nouvelles technologies et de design, c'est pourquoi j'ai tout de suite accroché avec WPF.

Ayant une formation d'Informatique Industrielle, je m'intéresse également à tout ce qui touche la robotique.

J'espère, à travers ce blog, partager avec vous les découvertes que je fais au cours de mon travail.

Bonne lecture !

Georges Legros

MCTS Winform & WPF

 ‭(Hidden)‬ Admin Links