Yet another blog about WPF, Surface, SL, MVVM, NUI....

2011

2010

2009

2008

 

Introducing the amazing WPF controls library on Codeplex !

25 October 2010

Hello everyone,

 

I am pleased to announce you the creation of the Amazing WPF controls library on Codeplex !

It will contains the differents controls I describe and/or peel on this blog. I will try to make an article for each control added to the library.

 

Here is a list of the currently available controls :

 

 

I also added to it the JetPack theme ported to WPF.

 

 

I hope you enjoy it !

 

http://amazingwpfcontrols.codeplex.com/



Shout it kick it on DotNetKicks.com

 

How to create an hand writing to text control (ink recognizer)

When building a (multi)touch application you may need one nice feature : translate hand-written text to real words. This open a whole new world full of possibilities like starting some actions when keywords are recognized or simply allow the users to write some text for later use. 

In this post we'll see all the step to create an hand writing to text control and how to tune it.

Continue reading...

 

[Performance tips] Use the system shadows instead of your own

27 April 2010

Today a fast and easy tip about shadows and performance.

In a project I have recently made, we've told the designer not to use BitmapEffects because they are performance killer. He so decided to create it's own shadows by duplicating each shape and make them looks like shadows(designer magic, voodoo things, etc...). I was then surprised to see that it kills performance too !


There is still the shaders effect which came with the 3.5 SP1 framework but they will be available only on vista or greater plateforms and their performance will depend of your graphic cards.

But we have an another ace in you deck : the system shadow which are quite fast even on software rendering!

Using it is quite easy :

  1. Add the PresentationFramework.Aero reference to your project,
  2. Add the following XML namespace : ”clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero”,
  3. Use the SystemDropShadowChrome element available with this namespace !



But there is a drawback : you can only produce squared shadows. But you can still play with the CornerRadius property to create simily round shadows.

Here is a little example of XAML code:

<UniformGrid
    xmlns:shadows="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
    Columns="2">
  <shadows:SystemDropShadowChrome Margin="25">
    <ListBox>
      <ListBoxItem Content="One item" />
      <ListBoxItem Content="Another item" />
      <ListBoxItem Content="Another third item" />
    </ListBox>
  </shadows:SystemDropShadowChrome >
 
  <shadows:SystemDropShadowChrome Margin="25" CornerRadius="800" Width="100" Height="100">
    <Ellipse Stroke="Black" Fill="White" />
  </shadows:SystemDropShadowChrome>
</UniformGrid>

Shadows screenshot

Shout it kick it on DotNetKicks.com




 

Simple properties Mapper by reflection : stop copying manually each property of your objects !

8 April 2010

There is time when you have to copy each property of an object to one another. This is called mapping and it's very fastidious to do it by hand.

In this post we'll see how to create a method extension which do it for you in one line of code !

When can it be useful

Here is a non exhaustive list of usage you can find to this snippet:

  • You want to reload the previous state of an object without changing it's instance : just clone it as a snapshot and copy back the properties when you want,
  • You get's some Data Transfert Object coming from WCF/Web services and you want's to fill a specific object with this data,
  • etc ...



I surely know this is not the most efficient way to solve these problems, but this is fast to use/understand and easy to implements.

Let's jump to the code !

What's inside ? Quite a few things actually ! There is two object, the source in which we take the data and the target in which we fill in these datas.

I use reflection to obtain every property of the source and then I check on the target if a property exist with the same name. If yes I fill it with the value of the property in the source object.

I also added a filter which is a list of Property name which will be ignored by the "copy process".

With a little more time you can also add a dictionnary which may map a property name in the source to an another property name in the target if the name are note exactly the same...

public static class PropetiesMapper{
	/// <summary>
    /// Copies all the properties of the "from" object to this object if they exists.
    /// </summary>
    /// <param name="to">The object in which the properties are copied</param>
    /// <param name="from">The object which is used as a source</param>
    /// <param name="excludedProperties">Exclude these proeprties from the copy</param>
    public static void copyPropertiesFrom(this object to, object from, string[] excludedProperties)
    {
 
      Type targetType = to.GetType();
      Type sourceType = from.GetType();
 
      PropertyInfo[] sourceProps = sourceType.GetProperties();
      foreach (var propInfo in sourceProps)
      {
        //filter the properties
        if (excludedProperties != null
          && excludedProperties.Contains(propInfo.Name))
          continue;
 
        //Get the matching property from the target
        PropertyInfo toProp =
          (targetType == sourceType) ? propInfo : targetType.GetProperty(propInfo.Name);
 
        //If it exists and it's writeable
        if (toProp != null && toProp.CanWrite)
        {
          //Copty the value from the source to the target
          Object value = propInfo.GetValue(from, null);
          toProp.SetValue(to,value , null);
        }
      }
    }
 
    /// <summary>
    /// Copies all the properties of the "from" object to this object if they exists.
    /// </summary>
    /// <param name="to">The object in which the properties are copied</param>
    /// <param name="from">The object which is used as a source</param>
    public static void copyPropertiesFrom(this object to, object from)
    {
      to.copyPropertiesFrom(from, null);
    }
 
    /// <summary>
    /// Copies all the properties of this object to the "to" object
    /// </summary>
    /// <param name="to">The object in which the properties are copied</param>
    /// <param name="from">The object which is used as a source</param>
    public static void copyPropertiesTo(this object from, object to)
    {
      to.copyPropertiesFrom(from, null);
    }
 
    /// <summary>
    /// Copies all the properties of this object to the "to" object
    /// </summary>
    /// <param name="to">The object in which the properties are copied</param>
    /// <param name="from">The object which is used as a source</param>
    /// <param name="excludedProperties">Exclude these proeprties from the copy</param>
    public static void copyPropertiesTo(this object from, object to, string[] excludedProperties)
    {
      to.copyPropertiesFrom(from, excludedProperties);
    }
  }



So, do you still want to put an "Hand made" label on your object's mapping ? :-D

A more complex and complete tool

For those which wants something more powerful and complete : take a look at the automapper library on codeplex.

Shout it kick it on DotNetKicks.com



 

Binding on a Property which is not a DependencyProperty

5 April 2010

A lot of controls expose properties which are not DependencyProperties and then you can’t put a binding on it. On some other cases, you only have a getter as accessor and you can’t put a binding on it too…

This is for example the case for the ribbon’s group of the office ribbon or the converter’s parameter.

If you ever tried to do so, you surely had an exception throwned :

A 'Binding' cannot be set on the 'SetCEDEJDED' property of type 'Tralala'.
A 'Binding' can only be set on a DependencyProperty of a DependencyObject.


In this post we will discover a work-around…

The main idea is to use a kind of proxy/observer (a definition can be found in this post) which will reflect every change on the source object to the target object and vice versa.

Here are the main parts of the solution ..

Specification: the XAML code we'll use

Here is the code snippet which describe how we will use our proxy in the XAML. There will be no code-behind.

<Window x:Class="BindOnNonDependencyProperty.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:us="clr-namespace:BindOnNonDependencyProperty"
    Title="BindOnNonDependencyProperty" >
  <DockPanel >
    <TextBox x:Name="myTextBox" DockPanel.Dock="Top"  />
    <TextBox x:Name="monTextBlockCible"  DockPanel.Dock="Top"  />
    <us:ExtendedBinding Source="{Binding ElementName=myTextBox,Path=Text,Mode=TwoWay}"
              Target="{Binding ElementName=monTextBlockCible,Path=Text,Mode=TwoWay}"
              />
  </DockPanel>
</Window>



The correct base class for our proxy/observer

We will call it ExtendedBinding and it must be inherithing from DependencyObject at last to be abble to own DependencyProperty. But the only way to add a DependencyObject into our XAML is to add it into a resourceDictonary.

This is a drawnback because, by doing it, it will no more be into the control's tree and then it will be impossible to make a binding on one of it's property. Note that it's still possible to use it as a Target from another place in our XAML but you can't do a Binding on one of it's properties. This code will not work :

<Windows.Resources>
   <MyDependencyObject x:Key="myKey" MyProperty="{Binding Tralala, ElementName=myTarget}" />
</Windows.Resources>



Then to put it insode the control's tree, we only had to make it an UIElement will you say... No because in the actual version of the Framework you won't have inheritance of the DataContext and the use of the 'ElementName' binding will be prohibited. Hopefully, there is a solution, our proxy have to inherit from FrameworkElement and everything will work fine !

The DependencyProperties

We will add two dependencyProperties, one will be the target and the second will be the source.

These DP will be customize by using the FrameworkPropertyMetadata two enables these features :

  • Binding will be done using the TwoWay mode,
  • The UpdateSourceTrigger used will be the PropertyChanged event.


How it works

The core of our proxy is to override the DependencyObject's OnPropertyChanged method. Each change on the source or the target will update it's counterparty.

We have to take care not to fall into a loop : when we will update the target or the source we'll also raise a PropertyChanged event and we must ignore this one....


Final code

public class ExtendedBinding : FrameworkElement
  {
    #region Source DP
    //We don't know what will be the Source/target type so we keep 'object'.
    public static readonly DependencyProperty SourceProperty =
      DependencyProperty.Register("Source", typeof(object), typeof(ExtendedBinding),
      new FrameworkPropertyMetadata()
      {
        BindsTwoWayByDefault = true,
        DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
      });
    public Object Source
    {
      get { return GetValue(ExtendedBinding.SourceProperty); }
      set { SetValue(ExtendedBinding.SourceProperty, value); }
    }
    #endregion
 
    #region Target DP
      //We don't know what will be the Source/target type so we keep 'object'.
    public static readonly DependencyProperty TargetProperty =
      DependencyProperty.Register("Target", typeof(object), typeof(ExtendedBinding),
      new FrameworkPropertyMetadata()
      {
        BindsTwoWayByDefault = true,
        DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
      });
    public Object Target
    {
      get { return GetValue(ExtendedBinding.TargetProperty); }
      set { SetValue(ExtendedBinding.TargetProperty, value); }
    }
    #endregion
 
    protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
    {
      base.OnPropertyChanged(e);
      if (e.Property.Name == ExtendedBinding.SourceProperty.Name)
      {
	//no loop wanted
        if (!object.ReferenceEquals(Source, Target))
          Target = Source;
      }
      else if (e.Property.Name == ExtendedBinding.TargetProperty.Name)
      {
	//no loop wanted
        if (!object.ReferenceEquals(Source, Target))
          Source = Target;
      }
    }
 
  }



Shout it kick it on DotNetKicks.com



 

Les nouveautés de WPF 4.0

11 February 2010

Hello all,

A post in french :

Je relaie les informations postées par moi-même sur un autre blog : Blog expertease Alti

C'est en français !

 

how do I detect double clic in JavaFX ?

14 December 2008

I am currently confronted to this problem: detect double clic in JavaFX.

What I want to do :

When you make a double click, you click twice, so this is what will occurs:

  • The first click will be catch and the simpleClickAction will be done (because clickCount != 2) ---> I don't want it : this is a double click and I want the simpleClick action to be perform only on single click !,
  • The second click will be catch and the double clickAction will be done --> This is what I want.


So what I want is :

  • To perform a simpleClick action on single click only (and not those which are part of a double click),
  • To perform a double click action on doubleClick only.


How I did it

In swing this is done by using timer. So why not do the same with a Timeline in JavaFX.


This is how I solve the problem (the code is also linked to this post) :

/*
 * Main.fx
 *
 * Created on 14 déc. 2008, 15:10:59
 */
 
package fr.antoinj.detectdoubleclick;
 
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.scene.Group;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.Scene;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.stage.Stage;
 
/**
 * @author Jonathan
 */
 
var textContent = "Nothing detected";
var clickInTheLastFewMoments: Boolean = false;
var lastLauchedTimeLine:Timeline ;
var clickedTimeLine: Timeline= Timeline {
    keyFrames: [KeyFrame {
            time: 0s
            action:function(){
                lastLauchedTimeLine.stop();
                clickInTheLastFewMoments=true;
            }
        }
        ,
        KeyFrame {
            time: 200ms
            action:function(){
                clickInTheLastFewMoments=false;
                simpleClick();
            }
        }
    ]
}
 
function simpleClick(){
    textContent="Simple click detected";
}
function doubleClick(){
    textContent="Double click detected";
}
Stage {
 
 
    title: "How I detect doubleClick in JavaFX"
    width: 400
    height: 80
    scene: Scene {
        content: Group{
            content: [Rectangle {
                    x: 75,
                    y: 0
                    width: 400,
                    height: 50
                    fill: Color.BLACK
                    onMouseClicked: function(me:MouseEvent){
                        if(clickInTheLastFewMoments){
                            clickInTheLastFewMoments=false;
                            clickedTimeLine.stop();
                            doubleClick();
                        }else {
                            clickedTimeLine.playFromStart();
                        }
                    }
                },
 
                Rectangle {
                    x: 0,
                    y: 0
                    width: 75
                    height: 50
                    fill: Color.ORANGERED
                    onMouseClicked: function(me:MouseEvent){
                        textContent="Nothing detected";
                    }
 
                },
                Text {
                    font: Font.font("Verdana",FontWeight.BOLD,12)
                    fill: Color.BLACK
                    x: 8
                    y: 25
                    content: "REFRESH"
                }
                ,
                Text {
                    font: Font.font("Verdana",FontWeight.MEDIUM,24)
                    fill:Color.PINK
                    x: 80
                    y: 30
                    content: bind textContent;
                }]
 
        }
 
    }
}

You can also see a demo of this javaFx apps here : link to the demo page or launch this JNLP : link to the JNLP



My question is : Do you have a better way to do this ?