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

2011

2010

2009

2008

 

MVVM - How to integrate the Office Ribbon respecting the pattern (especially the commands)

4 March 2010

Synopsis

The ribbon controls - introduced by office 2007 -are available for free on the Microsoft Office web site (French users should set the language to "english" to access the ressources). They can leverage the user's experience of your application and are pretty simple to use.

When I wanted to add them into one of my application I realized that it was broking the M-V-VM pattern.

In this post, we will see how to use the Ribbon, then what exactly is the issue and finally examine the solution I use as a work-around.

How to use the ribbon

This is very easy, here are the steps :

  • Download the library on the web site (http://msdn.microsoft.com/fr-fr/office/aa973809.aspx),
  • Add a reference to the dll in your project and dclare in the XAML this XML namespace : clr-namespace:Microsoft.Windows.Controls.Ribbon;assembly=RibbonControlsLibrary
  • Then you are free to use the ribbon's controls.


A central part of the Ribbon library is the RibbonCommand. A RibbonCommand is a WPF command plus a lot of things related to how it's presented : a label, a description, an large image, a small image, etc.... Then every button, combobox, checkbox, ... used in the Ribbon use these infos to change the way they are presented. Here is a little example : MVVMRibbonExample

<Window x:Class="MVVMRibbon.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:r="clr-namespace:Microsoft.Windows.Controls.Ribbon;assembly=RibbonControlsLibrary"
    Title="MainWindow" Height="350" Width="525">
 
  <Window.Resources>
    <r:RibbonCommand x:Key="MyFirstCommand" LabelTitle="A command"
        LabelDescription="A command description"
        LargeImageSource="/MVVMRibbon;component/antoine64x64.jpg"
        SmallImageSource="/MVVMRibbon;component/antoine64x64.jpg"
        Executed="RibbonCommand_Executed" CanExecute="RibbonCommand_CanExecute" />
 
    <r:RibbonCommand x:Key="ApplicationMenuCommand"
        LargeImageSource="/MVVMRibbon;component/antoine64x64.jpg"
        SmallImageSource="/MVVMRibbon;component/antoine64x64.jpg" />
  </Window.Resources>
 
  <DockPanel LastChildFill="True">
    <r:Ribbon DockPanel.Dock="Top">
      <!--I hide the QuickAccessToolBar because I have no use of it-->
      <r:Ribbon.QuickAccessToolBar>
        <r:RibbonQuickAccessToolBar Visibility="Collapsed" />
      </r:Ribbon.QuickAccessToolBar>
 
      <!--Here is the ApplicationMenu : the bubble acting as a main menu in Office-->
      <r:Ribbon.ApplicationMenu>
        <r:RibbonApplicationMenu  Command="{StaticResource ApplicationMenuCommand}" />
      </r:Ribbon.ApplicationMenu>
 
      <!-- And finally the well-know "tabs"-->
      <r:RibbonTab Label="A first tab">
        <!--The controls are grouped in the tabs-->
        <r:RibbonGroup>
          <r:RibbonButton Command="{StaticResource MyFirstCommand}" />
        </r:RibbonGroup>
      </r:RibbonTab>
 
      <r:RibbonTab Label="A second tab"></r:RibbonTab>
    </r:Ribbon>
 
    <FlowDocumentReader />
  </DockPanel>
</Window>


Why using the RibbonCommand is broking the pattern

As you can see in the code above, when you declare the RibbonCommands in the XAML, you have to set a Execute and CanExecute event's handler. These handlers are set in the code behind and this is what breaks the pattern.

Sow why not only declare RibbonCommand inside the viewModels ? Because this will put presentation informations (those inside the RibbonCommand like images, description) inside the ViewModel which one must be decoupled from the way the data is presented.

Actually, only declaring RibbonCommands inside the ViewModel breaks the pattern because it exist a very strong link between the data and how it's presented in these objects.

An another thing is that you can't bind anything to the Ribbon commands because : A 'Binding' cannot be set on the 'XXX' property of type 'RibbonCommand'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.... Yes, a RibbonCommand is not a DependencyObject.

So I can't use the ribbon ?

Nooooo ! A solutions exists : first you can create some kind of proxies to the command which will make the commands available as a ressource in the views(CommandReference) through binding. Then the view will be responsible to create the RibbonCommands as they which from these commands in the ressources. To this purpose we'll have to extend the standard RibbonCommand to make them accepts a Command as a property.

Ok, ok, I heard your question : why not directy make the extended RibbonCommands acts as a proxy ? The answere is that RibbonCommand does not inherits from DependencyObject and so we can't bind anything on it :-( ! (Which means, by the way, that we can't bind the commands of the viewModels directly to them).

I did not invent this technique, it's from :



The proxy for the commands

As pointed out in this article I call them CommandReference.

We declare a DependencyProperty on which we will bind the command in the ViewModel. As you can see, this class is also a ICommand : all the calls will be translated to the binded command.

public class CommandReference : Freezable, ICommand
{
public static readonly DependencyProperty CommandProperty = 
  DependencyProperty.Register("Command", typeof(ICommand), typeof(CommandReference), 
     new PropertyMetadata(new PropertyChangedCallback(OnCommandChanged)));
public ICommand Command
{
  get { return (ICommand)GetValue(CommandProperty); }
  set { SetValue(CommandProperty, value); }
}
 
#region ICommand Members
public bool CanExecute(object parameter){ 
  return (Command != null) ?Command.CanExecute(parameter):false;
}
 
public void Execute(object parameter){ Command.Execute(parameter);}
 
public event EventHandler CanExecuteChanged;
private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
  CommandReference commandRef = d as CommandReference;
  if (commandReference != null)
  {
	ICommand lastCommand = e.OldValue as ICommand;
	if (oldCommand != null) lastCommand .CanExecuteChanged -= commandRef .CanExecuteChanged;
 
	ICommand nextCommand = e.NewValue as ICommand;
	if (newCommand != null) nextCommand .CanExecuteChanged += commandRef .CanExecuteChanged;
  }
}
#endregion
 
#region Freezable
protected override Freezable CreateInstanceCore()
{
  return new CommandReference();
}
#endregion

The extended RibbonCommands

We simply add a ICommand property to the RibbonCommand wich one we will be abble to fill in with a StaticRessource.

public class RibbonCommandExtended : RibbonCommand
{
  private ICommand _command;
  public ICommand Command
  {
    get { return _command; }
    set
    {
      _command = value;
      if (_command != null)
      {
        this.CanExecute += us_CanExecute;
        this.Executed += us_Executed;
      }
      else
      {
        this.CanExecute -= us_CanExecute;
        this.Executed -= us_Executed;
      }
    }
  }
 
  private void us_Executed(object sender, ExecutedRoutedEventArgs e)
  {
    Command.Execute(e.Parameter);
  }
 
  private void us_CanExecute(object sender, CanExecuteRoutedEventArgs e)
  {
    e.CanExecute = Command.CanExecute(e.Parameter);
  }
}


Then, what will my XAML looks like .

Here it is, especially for you, very simple :

<Window.Resources>
  <fwk:CommandReference x:Key="MyCommandReference"
      Command="{Binding MyViewModelCommand}" />
  <fwk:RibbonCommandExtended x:Key="cmd_MyCommand" LabelTitle="A labek"
      LabelDescription="A description"
      Command="{StaticResource MyCommandReference}"
      LargeImageSource="/MVVMRibbon;component/antoine64x64.jpg"
      SmallImageSource="/MVVMRibbon;component/antoine64x64.jpg" />
</Window.Resources>

Then you use the RibbonCommandExtended as you will have used the standard RibbonCommand.

Isn't it a little long to make something pretty simple ? The answer is definitively yes but the Microsoft seems to be working on new version of the ribbon which will respects the M-V-VM pattern...

Why not using our RamoraPattern ?

This is not possible because as I pointed out before, the RibbonCommands are not DependencyObject and so we can't attach properties to them :-( !



Links

Here are some links you may find interesting on the same subjects :


Shout it kick it on DotNetKicks.com



 

MVVM : How to keep collections of ViewModel and Model in sync

2 March 2010

As pointed out in this post collections of the ViewModels and the models are not sync. This is because we do not access directly to the model but to an ObservableCollection(in the viewModel) which contains the object of the original collection(in the model) and that these two collections are not the same...

As pointed out in the comments on CodeProject, there is work-around. I try here to present two of them !

A first solution : register to the wrapping collection changes

The first solution is to register to the events of the ObservableCollection in your ViewModel and to translate the changes to the wrapped collection.
It is very straighforward but it becomes very fastidious if you have a lot of collections to deal with.

Here is the code :

//Wrap the business object collection
_friendsName = new ObservableCollection<string>(myBusinessObject.FriendsName);
//Register to the wrapping CollectionChanged event
_friendsName.CollectionChanged += new NotifyCollectionChangedEventHandler(_friendsName_CollectionChanged);
 
...
 
//Translate the changes to the underlying collection
void _friendsName_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
 switch (e.Action)
 {
  case NotifyCollectionChangedAction.Add:
   _myBusinessObject.FriendsName.AddRange(
    e.NewItems.OfType<String>()
    );
   break;
  case NotifyCollectionChangedAction.Remove:
   _myBusinessObject.FriendsName.RemoveAll(
    friendName => e.OldItems.Contains(friendName)
    );
   break;
  //Reset = Clear
  case NotifyCollectionChangedAction.Reset:
   _myBusinessObject.FriendsName.Clear();
   break;
 }
}



Another solution : create a proxy

You also can create a class which will act as a Proxy to the businessObject. Its only function will be to leverage the INotifyCollectionChanged events when necessary. I called it MVMCollectionSyncher for ModelViewModelCollectionSyncher and here is the code (which is very straightforward) :

public class MVMCollectionSyncher<T> : ICollection<T>, IDisposable, INotifyCollectionChanged
{
 #region fields
 private ICollection<T> _wrappedCollection;
 #endregion
 
 public MVMCollectionSyncher(ICollection<T> wrappedCollection)
 {
  if (wrappedCollection == null)
   throw new ArgumentNullException(
    "wrappedCollection",
    "wrappedCollection must not be null.");
  _wrappedCollection = wrappedCollection;
 }
 
 #region ICollection<T> Members
 public void Add(T item)
 {
  _wrappedCollection.Add(item);
  FireCollectionChanged(
   new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
 }
 
 public void Clear()
 {
  FireCollectionChanged(
   new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
  _wrappedCollection.Clear();
 }
 
 public bool Contains(T item)
 {
  return _wrappedCollection.Contains(item);
 }
 
 public void CopyTo(T[] array, int arrayIndex)
 {
  _wrappedCollection.CopyTo(array, arrayIndex);
 }
 
 public int Count
 {
  get { return _wrappedCollection.Count; }
 }
 
 public bool IsReadOnly
 {
  get { return _wrappedCollection.IsReadOnly; }
 }
 
 public bool Remove(T item)
 {
  if (_wrappedCollection.Remove(item)) {
   FireCollectionChanged(
     new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item));
   return true;
  }
  return false;
 }
 
 #endregion
 
 #region IEnumerable<T> Members
 public IEnumerator<T> GetEnumerator()
 {
  return _wrappedCollection.GetEnumerator();
 }
 #endregion
 
 #region IEnumerable Members
 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
 {
  return _wrappedCollection.GetEnumerator();
 }
 #endregion
 
 #region INotifyCollectionChanged Members
 public event NotifyCollectionChangedEventHandler CollectionChanged;
 private void FireCollectionChanged(NotifyCollectionChangedEventArgs eventArg)
 {
  NotifyCollectionChangedEventHandler handler = CollectionChanged;
  if (handler != null) handler.Invoke(this, eventArg);
 }
 #endregion
 
 #region IDisposable Members
 public void Dispose() { _wrappedCollection = null; }
 #endregion
}



Then in your ViewModel instead of presenting an ObservableCollection<> you offer an MVMCollectionSyncher with this code.

//Creation
MVMCollectionSyncher _friendsName = new MVMCollectionSyncher<string>(myBusinessObject.FriendsName);
...
//Property
public MVMCollectionSyncher<String> FriendsName
{
 get { return _friendsName; }
 set
 {
  if (value != null){
   _friendsName.Dispose();
   _friendsName = value;
   FirePropertyChanged("FriendsName");
  }
 }
}



Here are some links dealing on the same subject :



Shout it kick it on DotNetKicks.com
 

MVVM - Creating ViewModel : use XAML Power Toys (solution 2 of n).

Here is the next episode of our serie MVVM - Creating ViewModel. A list of all the article about creating a ViewModel is here..

Today we are going to discover a tool which can help us to create the ViewModel.

XAML Power Toys : add-in for VisualStudio

XAML Power Toys is an extremly useful add-in(build by Karl SHIFFLET) for VisualStudio that you can find at this URL : http://karlshifflett.wordpress.com/xaml-power-toys/. It is also available for Visual Studio 2010 since the 13 February 2010

With this add-in, you just have to make a right-click on you class and configure the viewModel that will be created. Then it copy into the clipboard the code of the corresponding ViewModel. Quite easy :-).

The only drawbacks is that it can be very long to do this for every object and I didn't find a way to automate the operation for a whole library of BusinessObjects...

RightClick : XAMLPowerToysCreateVM
Configuration screen :

v5001viewmodel_thumb

Do you know any other tool performing the same useful things ?



Shout it kick it on DotNetKicks.com




 

DependencyProperties or INotifyPropertyChanged ?

1 March 2010

When you want to make an object binding-aware you have two choices : implement INotifyPropertyChanged or create DependencyProperties. Which one is the best ? Let's try to answer this question !


How to implement INotifyPropertyChanged

Declaring that your class is implementing INotifyPropertyChanged adds an PropertyChangedEventHandler that you raise for every changes of the properties. We also add a little tricky method checkIfPropertyNameExists(String propertyName) which checks by reflection when debugging if the property name really exists ! You usually ends up with code like this :

/// <summary>
/// Base class for all my viewModel.
/// </summary>
public class ViewModelBase : INotifyPropertyChanged
{
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
public void FirePropertyChanged(String propertyName)
{
  checkIfPropertyNameExists(propertyName);
  PropertyChangedEventHandler handler = PropertyChanged;
  if (handler != null)
    handler.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
 
#endregion
 
[Conditional("DEBUG")]
private void checkIfPropertyNameExists(String propertyName)
{
  Type type = this.GetType();
  Debug.Assert(
    type.GetProperty(propertyName) != null,
    propertyName + "property does not exist on object of type : " + type.FullName);
}
}


As you can see, the code is quite easy to write and understand. You have to be very vigilant in checking the name of the property you gives as refactoring do not impacts Strings values but it stays quite simple.

DependencyProperties


MSDN definition of a DependencyProperty (link to) : a property that exists on a DependencyObject, is stored by the DependencyObject property store, and is identified by a DependencyProperty identifier on the owning DependencyObject.

Here is an example of how to create a DependencyProperty :

public class MyDependencyObject : System.Windows.DependencyObject
{
 public static readonly System.Windows.DependencyProperty MyDependencyPropertyProperty =
  System.Windows.DependencyProperty.Register("MyDependencyProperty", typeof(String), typeof(MyDependencyObject));
 
 public String MyDependencyProperty
 {
   get { return (String)GetValue(MyDependencyObject.MyDependencyPropertyProperty); }
   set { SetValue(MyDependencyObject.MyDependencyPropertyProperty, value); }
 }
}



Which one choose ?

Performances

All the tests are done under the .NET framework 4.0 with VisualStudio 2010 and .NET Memory Profiler 3.5.
The tests were already done on this page MVVM – Lambda vs INotifyPropertyChanged vs DependencyObject but I do not get the same results...

Execution times

To tests this I created a simple application and two textblocks binded to two String on my ViewModel. The tests were performed one by one and I took care to remove the inheritance of my ViewModel from DependencyObject when testing the INotifyPropertyChanged.

The code used to tests DependencyProperty is this one :

public static readonly DependencyProperty StringWithDependencyPropertyProperty =
DependencyProperty.Register("StringWithDependencyProperty", typeof(String), typeof(MainViewModel));
public String StringWithDependencyProperty
{
  get { return (String)GetValue(MainViewModel.StringWithDependencyPropertyProperty); }
  set { SetValue(MainViewModel.StringWithDependencyPropertyProperty, value); }
}
...
DateTime start = DateTime.Now;
for (int i = 0; i < 100000; i++)
  _mainViewModel.StringWithDependencyProperty = i.ToString();
DateTime end = DateTime.Now;
Console.WriteLine("Total time for DependencyProperty : " + (end - start).TotalMilliseconds +" ms.");


The code used to tests INotifyPropertyChangedis this one :

public String StringWithINotifyPropertyChanged
{
 get { return _stringWithINotifyPropertyChanged; }
 set
  {
    _stringWithINotifyPropertyChanged = value;
    firePropertyChanged("StringWithINotifyPropertyChanged");
  }
}
...
DateTime start = DateTime.Now;
for (int i = 0; i < 100000; i++)
  _mainViewModel.StringWithINotifyPropertyChanged = i.ToString();
DateTime end = DateTime.Now;
Console.WriteLine("Total time for INotifyPropertyChanged : " + (end - start).TotalMilliseconds+" ms.");


The results, for NO binding of the properties, were these :

Total time for DependencyProperty : 45 ms.
Total time for INotifyPropertyChanged : 171 ms.

The results, for one binding of the properties, were these :

Total time for DependencyProperty : 489 ms.
Total time for INotifyPropertyChanged : 1125 ms.

The results, for twelve binding of the properties, were these :

Total time for DependencyProperty : 3600ms.
Total time for INotifyPropertyChanged : 8375 ms.

DPvsInotifyPropertyChangedExecTimeChart
==> DependencyProperty is 2,30 times faster than INotifyPropertyChanged for one binding and this number does not increase with the number of binded controls.!

Edit : as argued in the comments on codeProject and even if it is not the most common way to use INotifyPropertyChanged , I have made the tests with a static event args, and the results are :

Total time for no binding: 154ms
Total time for one binding: 770ms
Total time for twelve bindings: 5605ms

==> DependencyProperies are still better, even if it's less...

Memory usage

I executed the same code and profiled the memory usages :

DependencyProperty created 600 new instances and add 44,583 bytes INotifyPropertyChanged created 876 new instances and add 63,536 bytes

DPvsInotifyPropertyChangedMemoryUsageChart
==> DependencyProperty seems (in my tests) to create less instance and to use less memory than the INotifyPropertyChanged system...

Inheritance issues

To create a DependencyProperty your objects needs to inherit from DependencyObject. This is not always possible and then using INotifyPropertyChanged is the only way to make it Bindable-aware.

Also, by being a DependencyObject, your object will carry with it all the dependency engine stuff and these limitations:


Inheritance from a base class you do not have a grip on ?=> No DependencyProperty !

Animations

Using DependencyProperty make the poperties animatable. If you want to animate a property, there is no simple work-around because, as the MSDN says : In order to be animated, the animation's target property must be a dependency property.

If you can't use DependencyProperty (when you do not create the objects for example), there is still work-arounds techniques.

Flexibility

Using INotifyPropertyChanged is sometimes more flexible than using DependencyProperty. Let me explain that. When you build a screen on which a lot of controls visibility dependsof some rules, you may declare a boolean which value is computed from other boolean.

For example, IsEditionPosible must be set to true only if IsAlreadyInEditionMode = false and if UserHasEditionRights = true. So when changing the value of IsAlreadyInEditionMode or UserHasEditionRights you must tells the binding engine that IsEditionPosible has been updated too. It's easier to do this with INotifyPropertyChanged than with the DependencyProperty with which you should have to create a method, which recalculate and reassign the new value to IsEditionPosible . Here you just have to use this little snippet :

public Boolean IsAlreadyInEditionMode 
{
 get { return _isAlreadyInEditionMode ; }
 set
  {
    _isAlreadyInEditionMode = value;
    firePropertyChanged("IsAlreadyInEditionMode ");
    firePropertyChanged("IsEditionPosible");
  }
}
 
public Boolean UserHasEditionRights 
{
 get { return _userHasEditionRights ; }
 set
  {
    _userHasEditionRights = value;
    firePropertyChanged("UserHasEditionRights");
    firePropertyChanged("IsEditionPosible");
  }
}
 
public Boolean IsEditionPosible
{
 get { return UserHasEditionRights && !IsAlreadyInEditionMode  ; }
}


Note that this is the way that I create computed value for easier binding in my viewModel but this is a subject where improvments may be done...

Flexibility (easier code writing) needed ?=> Choose INotifyPropertyChanged !

Testing

When you performs testing on your object, you will be in trouble if you use DependencyObject : the test are not done on the same thread that created the object and then throws you a "System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it".

Testing => No DependencyProperty !

Code Readability/writing

Some people argues that the use of DependencyProperties the code extremely ugly. I myself think that this is exaclty the same. To make easier the creation of dependencyProperty you can use this snippet : link to the snippet


Links of articles on the same subject :



Shout it kick it on DotNetKicks.com


 

MVVM - Creating ViewModel : wrap your business object (solution 1 of n).

24 February 2010

Intro

When you create WPF applications, you may (or you should !) use the M-V-VM pattern and so have to use/create ViewModel. The viewModel job is mainly to expose properties of your businessObjects to your views, ready for binding.

To be ready for the binding the most used solution is to implement INotifyPropertyChanged and to fire events fo every change made. An issue is that you often do not create the business object used by the application which are created by another team and that these object are not ready for binding. So you must find a solution to create an object which will in fact be very similar of your business object BUT ready for binding.

In this serie of post I will try to give some of the solution we can use to do so. A list of all the article is here..

Wrap your business object(solution 1 of n)

The first solution which appears in every developper's brain is to wrap theBusinessObject(BO) into the viewmodel. Every properties of your ViewModel will actually be some kind of proxy to/from the underlying BO.

For example let's take for granted that you have a businessObject like this :

/// <summary>
/// I'am the business object created by another team. I'am not binding-aware : shame on me !
/// </summary>
public class MyBusinessObject
{
  public String LastName { get; set; }
  public String FirstName { get; set; }
  public int Age { get; set; }
  public List<String> FriendsName { get; set; }
}


You will then gives the Business object to your viewModel which will act as a proxy. the result will be something like this :

public class ViewModelWrapped : ViewModelBase
{
private MyBusinessObject _myBusinessObject;
private ObservableCollection<String> _friendsName;
 
public ViewModelWrapped(MyBusinessObject myBusinessObject)
{
  _myBusinessObject = myBusinessObject;
  _friendsName = new ObservableCollection<string>(myBusinessObject.FriendsName);
}
 
public String FirstName
{
  get { return _myBusinessObject.FirstName; }
  set
  {
    FirePropertyChanged("FirstName");
    _myBusinessObject.FirstName = value;
  }
}
 
public String LastName
{
  get { return _myBusinessObject.LastName; }
  set
  {
    FirePropertyChanged("LastName");
    _myBusinessObject.LastName = value;
  }
}
 
public int Age
{
  get { return _myBusinessObject.Age; }
  set
  {
    FirePropertyChanged("Age");
    _myBusinessObject.Age = value;
  }
}
 
public ObservableCollection<String> FriendsName
{
  get { return _friendsName; }
  set
  {
    if (value != null)
    {
      FirePropertyChanged("FriendsName");
      _myBusinessObject.FriendsName = value.ToList<String>();
    }
  }
}
}



Notes : Something interesting to look at is how we wrap our collections to make them bindable : quite a job ! More over the model and the viewModel list are no more synched... The list object itself is synched but the operation on the collection will be made on the viewModel collection and no more on the model collection. In this case adding or removing a friend's name will affect only the ViewModel and not the model.


Pros and cons

Pro :

  • The name of the properties exposed to your views can be differents from those in the business object
  • It's very easy to understand the code when you read it again, even a few months later



Cons:

  • It's a very boring job to re-create the properties of the viewModel to map those from the BO
  • Collection and Set of the model are no more synched with the ViewModel
  • Copy-cut code can leads to error, especially when raising INotifyPropertyChanged events where case matters



NB: I've found an article of Josh Smit on this subject that you may find useful too.
and this link too : MVVM: To Wrap or Not to Wrap? How much should the ViewModel wrap the Model? (Part 1)

Shout it kick it on DotNetKicks.com
 

WPF - catch events even if they are already handled

19 February 2010

As you may actually know WPF introduced the routed events. These last are no more specific to a single control but they are routed inside the tree of your controls.

If you want to stop an event, you can mark it as Handled. If so, the routing engine will stop to propage it. In fact this is just an illusion because the engine will only stop leveraging your handlers.

But sometimes, for example when you are using a control from third parties, you want to catch the events even if marked as handled. Here is the little piece of code to use :

anyUIElement.AddHandler(
    UIElement.MouseEnterEvent,
    (RoutedEventHandler)OnMouseEnterCallMeAlways,
    true
    );


This method can be called on any UIElement, in code only. The important part here is the Boolean (true) which tells the engine to call the handle even if the events is marked as handled.


Shout it kick it on DotNetKicks.com
 

Use AttachedProperties to add behaviors to the components (Ramora pattern)

The problem

In WPF you expect your components/controls to behave exactly as you want to.... but this not always the case.
For example : why does this combobox not execute a command when I change the selection or more often why this textbox does not execute a command when I press the Enter (return) key ?

This problem often occurs when you use the - well know - pattern M-V-VM and it's sometimes hard to find a workaround. Today I will explain you a design pattern, know as the Ramora pattern which I find very useful.
By the way, you can also use it to create a library of behaviors for all your projects...

Wanted application

Ramora pattern

One solution (or the ramora pattern explained)


The idea

The solution is based on the attached properties (MSDN page here) of the WPF binding engine. With this mechanism you can attach any property to any object you want and it's massively used in layout controls (DockPanel.Dock for example)..

By attaching and detaching properties we will attach some handlers on the events of our choice to add behaviors to the controls. The value passed by the property will also be useful as a data storage....


The steps are :

  1. Create a class of your choice, no inheritance needed,
  2. Declare an attachedProperty by registering it and adding the corresponding GetXXX and SetXXX,
  3. Add an event handler to the change of this property : inside it, add an event handler to the event you want to catch (for example MouseEnter),
  4. Add the behavior logic inside this last event handler
  5. Attach this behaviors to the aimed control inside your XAML (after you'd declared the XMLNS)


An example

In this example we'll try to add a nice beahavior to any IInputElement : anytime the user presses the 'Enter' key, it will execute a Command.

We'll then declare a Command attached property of type 'ICommand' which will be the command to execute on a given event (very original isnt it ?).

#region Command Property
/// <summary>
/// Enables Command functionality
/// </summary>
public static ICommand GetCommand(DependencyObject obj)
{
	return (ICommand)obj.GetValue(CommandProperty);
}
 
/// <summary>
/// Enables Command functionality
/// </summary>
public static void SetCommand(DependencyObject obj, ICommand value)
{
	obj.SetValue(CommandProperty, value);
}
 
/// <summary>
/// Enables Command functionality
/// </summary>
public static readonly DependencyProperty CommandProperty =
	DependencyProperty.RegisterAttached("Command",
 typeof(ICommand),
 typeof(CommandOnEnter), 
new UIPropertyMetadata(null, new PropertyChangedCallback(CommandPropertyChanged)));



Then everytimes the property is assigned we will attach or detach our event handlers on the DependencyObject which uses it. In our case this is an IInputElement.

/// <summary>
/// Command property changed callback
/// </summary>        
static void CommandPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
	//Test in debug mode if it's binded to the correct type of element...
	Debug.Assert(sender is IInputElement, "Attached property only for a IInputElement");
	if (sender is IInputElement)
	{
		IInputElement inputElement = sender as IInputElement;
 
		// Clean when Command is released
		if (e.OldValue != null)
		{
			Detach(inputElement);
		}
 
		//Attach the behavior
		if (e.NewValue != null)
		{
			Attach(inputElement);
		}
 
	}
}
 
/// <summary>
/// Clean event handlers
/// </summary>
/// <param name="inputElement">The aimed IInputElement</param>
private static void Detach(IInputElement inputElement)
{
	inputElement.PreviewKeyDown -= CommandOnEnter_PreviewKeyDown;
	if (inputElement is FrameworkElement)
		(inputElement as FrameworkElement).Unloaded -= CommandOnEnter_Unloaded;
}
 
 
private static void Attach(IInputElement inputElement)
{
	inputElement.PreviewKeyDown += new KeyEventHandler(CommandOnEnter_PreviewKeyDown);
	if (inputElement is FrameworkElement)
		(inputElement as FrameworkElement).Unloaded += new RoutedEventHandler(CommandOnEnter_Unloaded);
 
}



The keyPressed event handler checks if the enter key is pressed and execute the command if yes. The command to execute is retrieved via the attachedProperties system of WPF (GetValue method) :

static void CommandOnEnter_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
	if (sender is IInputElement)
	{
		var textBox = sender as IInputElement;
		if (e.Key == Key.Enter && e.KeyboardDevice.Modifiers == ModifierKeys.None)
		{
			ICommand cmd = GetCommand(sender as DependencyObject) as ICommand;
			cmd.Execute(null);
		}
 
	}
}



That's all !

Adding a parameter ?

What if you want to pass a parameter to the executed Command ? You will simply have to add another Attached property and get it's value in the keyPressed event handler.

/// <summary>
/// Enables CommandParameter functionality
/// </summary>
public static object GetCommandParameter(DependencyObject obj)
{
	return (object)obj.GetValue(CommandParameterProperty);
}
 
/// <summary>
/// Enables CommandParameter functionality
/// </summary>
public static void SetCommandParameter(DependencyObject obj, object value)
{
	obj.SetValue(CommandParameterProperty, value);
}
 
/// <summary>
/// Enables CommandParameterProperty functionality
/// </summary>
public static readonly DependencyProperty CommandParameterProperty =
	DependencyProperty.RegisterAttached("CommandParameterProperty", typeof(object), typeof(CommandOnEnter));

Funny things to do

The ramora pattern can be used to do a lot of things, here is a list of some I'am thinking :

  • Execute a command on a textbox when pressing enter,
  • Select all the text when a textbox gets the focus,
  • Etc...



Here are some links you may find useful :

  1. Thinking in WPF: attached properties
  2. More advanced attached property use: the Ramora pattern
  3. Behaviors in Silverlight 4.0



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 to scale around a specific point and not the center of the Element

11 October 2009

The problem


The most popular controls which has been brought by the Microsoft SDK is certainly the scatterView. Each item is positioned at a random place with a random orientation.
ExampleOfScatterView

You can then rotate, move or scale them with your fingers. Here we will focus on this last point : the scaling. This is a really nice feature and you may wants to put it in your application (it may also be replace my a mouse wheel or stylus events, etc.).

If an user wants to zoom-in on a specific part of the presented items, he wills do a 'scale manipulation' with it's fingers on the specific part.

Simple, will you think : we just have to change the width and the height of the control based on the scale delta ! But the problem is that, the control will grow but the specific part wanted by the user will no more be under it's fingers. A figure worth a thousand words :
Schema example



My solution

Here we are going to scale a scatterViewItem with the property 'CanMove' set to false. We do it because, the scatterView item does already what we wants and this is done by a translation.


Also we are going to use a Affine2DManipulationProcessor which will gives us the scale value for a manipulation done by multiple fingers. If some are catching stylus events, you could use a ManipulationProcessor from the multiTouch SDK (available here :http://www.microsoft.com/downloads/details.aspx?FamilyID=12100526-ed26-476b-8e20-69662b8546c1&displaylang=en).

The XAML :

<s:ScatterView VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
      <s:ScatterViewItem x:Name="_myObjectToScale" Orientation="0" CanRotate="False" 
            CanScale="False" CanMove="False"
            Center="512.0,384.0"  ShowsActivationEffects="False"
            PreviewContactDown="_myObjectToScale_ContactDown" 
            PreviewContactUp="_myObjectToScale_ContactUp">
         <Image Source="Resources/myself.jpg" />
      </s:ScatterViewItem>


The code :

private Affine2DManipulationProcessor _ourManipProc;
public Affine2DManipulationProcessor OurManipProc { 
   get { return _ourManipProc; } 
   set { _ourManipProc = value; }
 }
 
public SurfaceWindow1()
{
    InitializeComponent();
    DataContext = this;
    _ourManipProc = new Affine2DManipulationProcessor(Affine2DManipulations.Scale, this);
 
    //Catch the event from our manipulation processor
    OurManipProc.Affine2DManipulationDelta += OurManipProc_Affine2DManipulationDelta;
}
 
 
private void _myObjectToScale_ContactDown(object sender, ContactEventArgs e)
{
    //this contact is tracked by ou MP
    OurManipProc.BeginTrack(e.Contact);
}
 
private void _myObjectToScale_ContactUp(object sender, ContactEventArgs e)
{
    //this contact is no more tracked by ou MP
    OurManipProc.EndTrack(e.Contact);
}



Then the important part, the Affine2DManipulationDelta handler which will do what we wants, I will describe it below.

void OurManipProc_Affine2DManipulationDelta(object sender, Affine2DOperationDeltaEventArgs e)
{
    double scaleDelta = e.ScaleDelta;
    if (scaleDelta == 1.0) return;
 
 
    Point manipOrigin = e.ManipulationOrigin;
    Point oldCenter = new Point(_myObjectToScale.Center.X, _myObjectToScale.Center.Y);
 
    double oldHeight = _myObjectToScale.ActualHeight;
    double newHeight = _myObjectToScale.ActualHeight * scaleDelta;
 
    double oldWidth = _myObjectToScale.ActualWidth;
    double newWidth = _myObjectToScale.ActualWidth * scaleDelta;
 
    _myObjectToScale.Height = newHeight;
    _myObjectToScale.Width = newWidth;
 
    double ratioX = Math.Abs(manipOrigin.X - oldCenter.X) / (oldWidth / 2);
    double newCenterXD = ratioX
        * Math.Sign(oldCenter.X - manipOrigin.X) * (newWidth - oldWidth) / 2;
 
    double ratioY = Math.Abs(manipOrigin.Y - oldCenter.Y) / (oldHeight / 2);
    double newCenterYD = ratioY *
        Math.Sign(oldCenter.Y - manipOrigin.Y) * (newHeight - oldHeight) / 2;
 
    if (scaleDelta > 1.0)
        _myObjectToScale.Center += new Vector(newCenterXD, newCenterYD);
    else
        _myObjectToScale.Center += new Vector(newCenterXD, newCenterYD);
}



Explanation


First we need to calculate the new size of our control. This is done by multiplying it's actual size by the scaleDelta gived by our processor.

Then we store some interesting values as the old size, the old center position, etc.

Then we calculate the ration for X and for Y. What is it ? It's ratio of the aimed point (the point on top of which the manipulation is done) and the half of the control size. But why do we need it ? Because we wants the controls to grow on each side of the aimed point, not only the one near the center. If we does not calculate this, one side of the control would stay at the same position during our manipulation. algo explanation

Next we calculate the center delta which is the translation we must operate on our control for the focused point to stay under our fingers (or mouse pointer, or stylus, whatever you wants :D).



We finaly apply all this measure to our control. That's it !

kick it on DotNetKicks.com Shout it


 

Tips: increase performances when using D3DImage in WPF

17 September 2009

Hello,

Often when you read articles explaining how to use a D3DImage in your WPF application you use code which directly handle the CompositorTarget.Rendering event by updating the 3D world... This can lead to performance problems.

For example in my application, WPF refresh the display with a FPS of 160 : the handler which recreate the 3D image is then call 160 times a second. No need to refresh this often.


The solution I used is to create a Timer which will do it at the FPS I want. Let's say 30FPS for example :

public void createTheRenderingWithCorrectFPS(int whichFPS){
   DispatcherTimer _timer = new DispatcherTimer();
   _timer.Interval = new TimeSpan(1000 /whichFPS);
   _timer.Start();
   _timer.Tick += new EventHandler(_timer_Tick);
}
void _timer_Tick(object sender, EventArgs e)
{
   //Refresh the 3D scene
}



This enables your application to be really more reactive especially that you need to be on the main thread to update the 3D scene...



Do you know a better way ?



kick it on DotNetKicks.com Shout it



 

GUI to NUI : representations and manipulation of OLAP data in 3D

21 July 2009

Hello,

Here is a little post to show you a little video presenting the project I have worked on during my 6 months of training. I am very proud of it :) :



The subject was to find the new way of representations and manipulations of OLAP Data without using a keyboard or a mouse.
This is done in 3D on the Microsoft Surface plateform.

The technologies involved are :

  1. Microsoft Surface for the NUI (Natural User Interface),
  2. (M)Ogre to create the 3D World,
  3. OLAP for the acquisition of datas.




Here are some links for those interested :

  1. What is OLAP ? (wikipedia)
  2. What are the NUI ? (wikipedia)
  3. What is Ogre the 3D engine ?
  4. What is Microsoft Surface ?
  5. What is the company in which I have done my training ?



People who worked on it :

  1. Development: Jonathan ANTOINE
  2. Supervision of the project : Elise DUPONT
  3. 3D Expert : Laurent TRUDU



Enjoy !


kick it on DotNetKicks.com


Shout it
 

CREATE, LAUNCH and CONTROL a WPF animation FROM CODE

7 July 2009

The problem

Sometimes you need to animate your specific object and for this purpose there is the WPF animation.

Here are the prerequireds :

  • The property you want to animate must be a DependencyProperty,
  • The property must so be a part of a DependencyObject,
  • Your object must implement IAnimatable to be able to launch the animation.


The difficulty resides in being able to create an animation, create a storyboard and set the corrects values for the attached properties - TargetName and TargetProperty - on the animation. All of this directly in the code.

You can then control the animation, the usual way than in XAML.

My solution/checklist

Here is how I did it, step by step.

First I make my business object derives from FrameWorkElement. Why ?
Because, this make my object a dependency object. Also, my object will implements IAnimatable ( FrameWorkElement heritate from UIElement which implements IAnimatable). And finally, it gets a NameScope which will be used later.
So here is my object:

public class Puppet: FrameworkElement {    }



Next I will had a DependencyProperty to be animated. Here I animate a value of type Point. I create all the usual things for the dependencyProperty and also add a storyboard (I will always use the same):

public class Puppet: FrameworkElement
{
   public static DependencyProperty ContactMovementProperty =
   DependencyProperty.Register("ContactMovement", typeof(Point), typeof(Puppet));
 
   public Point ContactMovement
   {
       get { return (Point)GetValue(SatelliteNavigator.ContactMovementProperty); }
       set { SetValue(SatelliteNavigator.ContactMovementProperty, value); }
    }
 
    private Storyboard stboard = new Storyboard();
}



Then, let's say I will create and launch the animation directly in the constructor. Here is the code added :

public class()
{
   //Maybe it was running before (if not set in the constructor)
   //stboard.Stop();
 
    double xFinal = 36;
    double yFinal = 36;
    PointAnimation animation = new PointAnimation();
 
    animation.From = ContactMovement;
    animation.To = new Point(xFinal , yFinal );
    animation.Duration = TimeSpan.FromMilliseconds(e.Velocity.Length*7 / deceleration);
    animation.AccelerationRatio = 0f;
    animation.DecelerationRatio = 0.4f;
    String puppetName= "puppet";
 
    NameScope nams = new NameScope();
    NameScope.SetNameScope(this, nams);
    this.RegisterName(puppetName, this);
 
    Storyboard.SetTargetName(animation, puppetName);
    Storyboard.SetTargetProperty(animation, new PropertyPath(Puppet.ContactMovementProperty));
 
    stboard.Children.Add(animation);
    stboard.Begin(this);
 
}


What is done ? First I create the animation with random values for our example.
Then I create a NameScope and set it to our object. Why ? Because it's not created by the runtime for our object and we need one. It will be used by the animation to retrieve the object to animate.

This is done by registering the Puppet object in the namescope and giving the same TargetName of the attachedProperty of the animation(Storyboard.SetTargetName).

Then we clear the children animation of the storyboard (maybe it was not empty) and launch the storyboard by giving it the Puppet (object in which the animated object is).



We can then use the usual methods on storyboard to control the play of the media. For example :

stboard.Stop();


Conclusion

As you can see this is not as easy as writing some XAML lines but it's not impossible !

Any questions ?

kick it on DotNetKicks.com


Shout it


 

XAML to PNG converter...

25 June 2009

Hello,

Today a post about creating a PNG from a XAML file. Easy some will says but we will see some more tips :

  • How to create a screenshot from a control in the size you want (not the actual size).
  • How to load an external XAML file and display it inside your application.



How to load an external XAML

This snippet will use a XAMLReader, and create a visual from the XAML and the put it inside you application :

Microsoft.Win32|>.OpenFileDialog dialog = new Microsoft.Win32|>.OpenFileDialog();
         dialog.Title = "Select the XAML file.";
         dialog.AddExtension = true;
         dialog.CheckFileExists = true;
         dialog.DefaultExt = ".xaml";
         dialog.Filter = "Xaml files |*.xaml";
 
         if (dialog.ShowDialog() == true)
         {
            String path = dialog.FileName;
            UIElement visual = XamlReader.Load(System.Xml.XmlReader.Create(path)) as UIElement;
            if (visual != null)
            {
               _docker.Children.Add(visual);
            }
            else
            {
               MessageBox.Show("Cannot load the UiElement from the XAML.", "Error", MessageBoxButton.OK);
               this.Close();
            }
         }


Quite simple in fact.

How to create a screenshot in the size you want...

Then to create a sample from a control or anything which is a visual you will use a different syntax than the one presented sooner in this blog.

The tips is to create a brush from the visual, and fill a Rectangle in a drawingContext.

Here is the code :

Visual theVisual = _docker; //Put the aimed visual here.
 
         //Get the size you wants from the UI
         double width = Convert.ToDouble(_widthTextB.Text);
         double height = Convert.ToDouble(_heightTextB.Text);
 
         if (double.IsNaN(width) || double.IsNaN(height))
         {
            throw new FormatException("You need to indicate the Width and Height values of the UIElement.");
         }
         Size size = new Size(width, height);
 
         DrawingVisual drawingVisual = new DrawingVisual();
         VisualBrush vBrush = new VisualBrush(theVisual);
 
         using (DrawingContext dc = drawingVisual.RenderOpen())
         {
            dc.DrawRectangle(vBrush, null, new Rect(new Point(), size));
         }
 
         RenderTargetBitmap render = new RenderTargetBitmap(
               Convert.ToInt32(1900),
               Convert.ToInt32(1200),
               96,
               96,
               PixelFormats.Pbgra32);
         // Indicate which control to render in the image
         render.Render(drawingVisual);
         Stream oStream = new FileStream("out.png", FileMode.Create);
 
         PngBitmapEncoder encoder = new PngBitmapEncoder();
         encoder.Frames.Add(BitmapFrame.Create(render));
         encoder.Save(oStream);
         oStream.Flush();
         oStream.Close();



The resulting app

There is a little drawback: the xaml visual you load must be configured to stretch when putted inside a layout control...
Here is some screenShot of the app running :

Xaml To Png Exporter



The code source is attached to the post.

kick it on DotNetKicks.com
 

Write text inside an image: add a poster to add it in your Mogre Scene

28 May 2009

Introduction

To display informations into your scene you can use a billboard represented by the MovableText into (M)ogre but sometimes you just want to put some static text somewhere because it's more readable.

For example :

Create a poster to add it in your Mogre Scene

The code

Here is the code which use a lot of my last article .

The steps are :

  1. Create a bitmap with the text in it,
  2. Create a texture with this image, then a material,
  3. Create a poster (rectangle) and put the texture on it,
  4. Return the manualObject created.

The part which may be interest you is how to get the right size for the created bitmap based on the text...

Also the creation of the manualObject is not necessary but I think it may interest some people to see how to use it.

/// <summary>
/// Creates a 'poster' based on a text.
/// </summary>
/// <param name="Smgr">The scenemanager (necesary to create the manual object).</param>
/// <param name="text">The text to put on the poster.</param>
/// <author>Jonathan ANTOINE</author>
private static ManualObject createALabel(SceneManager Smgr, String text)
{
String textureName = Guid.NewGuid().ToString();
System.Drawing.Font font = new System.Drawing.Font("Calibri", 12, FontStyle.Bold);
Bitmap bitmap = new Bitmap(1, 1);
Graphics g = Graphics.FromImage(bitmap);
 
SizeF measureString = g.MeasureString(text, font);
bitmap = new Bitmap((int)measureString.Width, (int)measureString.Height);
g = Graphics.FromImage(bitmap);
g.FillRectangle(Brushes.Black, new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height));
g.DrawString(text, font, new System.Drawing.SolidBrush(Color.White), new Point(3, 3));
 
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
 
Stream oStream = new MemoryStream();
g.Save();
bitmap.Save(oStream, ImageFormat.Png);
oStream.Flush();
 
//bitmap.Dispose();
//Back to the start of the stream
oStream.Position = 0;
 
//read all the stream
BinaryReader oBinaryReader = new BinaryReader(oStream);
byte[] pBuffer = oBinaryReader.ReadBytes((int)oBinaryReader.BaseStream.Length);
oStream.Close(); //No more needed
TextureManager.Singleton.Remove(textureName); //Remove eventually texture with the same name
unsafe
{
GCHandle handle = GCHandle.Alloc(pBuffer, GCHandleType.Pinned);
byte* pUnsafeByte = (byte*)handle.AddrOfPinnedObject();
void* pUnsafeBuffer = (void*)handle.AddrOfPinnedObject();
 
MemoryDataStream oMemoryStream = new MemoryDataStream(pUnsafeBuffer, (uint)pBuffer.Length);
DataStreamPtr oPtrDataStream = new DataStreamPtr(oMemoryStream);
 
Mogre.Image oMogreImage = new Mogre.Image().Load(oPtrDataStream, "png");
 
TextureManager.Singleton.LoadImageW(textureName, ResourceGroupManager.DEFAULT_RESOURCE_GROUP_NAME, oMogreImage);
 
//handle.Free();
}
String matNam = Guid.NewGuid().ToString();
MaterialPtr _dynamicMaterial = MaterialManager.Singleton.Create(matNam, ResourceGroupManager.DEFAULT_RESOURCE_GROUP_NAME);
Pass pass = _dynamicMaterial.GetTechnique(0).GetPass(0);
 
pass.ShadingMode = ShadeOptions.SO_PHONG;
 
TextureUnitState tus = pass.CreateTextureUnitState(textureName);
tus.SetTextureAddressingMode(TextureUnitState.TextureAddressingMode.TAM_CLAMP);
pass.AddTextureUnitState(tus);
 
_dynamicMaterial.Dispose(); //Dispose the pointer, not the material !
 
ManualObject manualObject = Smgr.CreateManualObject(Guid.NewGuid().ToString());
 
manualObject.EstimateIndexCount(6);
manualObject.EstimateVertexCount(6);
 
manualObject.Begin(matNam, RenderOperation.OperationTypes.OT_TRIANGLE_LIST);
 
//DESSUS
int yWidthVariable = bitmap.Width;
int xWidth = bitmap.Height;
 
manualObject.Position(new Vector3(0, 0, 0));
manualObject.TextureCoord(1, 0);
manualObject.Normal(Vector3.UNIT_Z);
 
manualObject.Position(new Vector3(0, -yWidthVariable, 0));
manualObject.TextureCoord(0, 0f);
manualObject.Normal(Vector3.UNIT_Z);
manualObject.Position(new Vector3(xWidth, 0, 0));
manualObject.TextureCoord(1f, 1);
manualObject.Normal(Vector3.UNIT_Z);
 
manualObject.Position(new Vector3(0, -yWidthVariable, 0));
manualObject.TextureCoord(0f, 0f);
manualObject.Normal(Vector3.UNIT_Z);
manualObject.Position(new Vector3(xWidth, -yWidthVariable, 0));
manualObject.TextureCoord(0f, 1.0f);
manualObject.Normal(Vector3.UNIT_Z);
manualObject.Position(new Vector3(xWidth, 0, 0));
manualObject.TextureCoord(1f, 1.0f);
manualObject.Normal(Vector3.UNIT_Z);
 
manualObject.End();
 
manualObject.CastShadows = false;
 
return manualObject;
}



Also you can get the size of the "poster" by using the boundingbox. An example of use :

manualObject.BoundingBox.Size.x * 0.5f * Vector3.UNIT_Y;

The code can be find as an attached file.

kick it on DotNetKicks.com
 

Use dataBinding and DependencyProperty with a non-WPF or extern object

10 April 2009

Today we are going to learn how we can uses the powerful data binding of WPF even on non-WPF objects.

The problem: when to use this solution ?

Sometimes you need to use the databinding with an object that you have not created and you can't use inheritance.

For example I wanted to use a Mogre Camera and build some WPF animation with it and I couldn't because :

  • WPF animation needed a DependencyProperty to manipulate,
  • I couldn't derive the Mogre.Camera class and add it the correct things because I got the camera from a factory object (the sceneManager).



Then I couldn't use the WPF animation to move my camera... next is how I solve it.

A solution: mine and surely not the best ;-)

Here is the solution i use:

  1. Create a proxy DependencyProperty inside a DependencyObject, for example your main windows.
  2. Override the OnPropertyChanged handler.
  3. Update the aimed attribute inside the handler.


To control my camera, I created this DependencyProperty inside my windows:

public static readonly DependencyProperty CameraPositionProperty = DependencyProperty.Register("CameraPosition", typeof(Point3D), typeof(SurfaceWindow1), new PropertyMetadata(new Point3D(0, 0, 0)));
 
      public Point3D CameraPosition
      {
         get
         {
            return (Point3D)GetValue(CameraPositionProperty);
         }
         set
         {
            SetValue(CameraPositionProperty, value);
         }
      }


Then I added this override :

protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
      {
         base.OnPropertyChanged(e);
         if (e.Property.Name.Equals("CameraPosition"))
         {
            _ogre.Camera.SetPosition((float)((Point3D)e.NewValue).X, (float)((Point3D)e.NewValue).Y, (float)((Point3D)e.NewValue).Z);
            _ogre.Camera.LookAt(Vector3.ZERO);
         }
      }



And my usual question :

Does someone have a better idea to perform the same ?



 

Calculate the real difference between two angles, keeping the correct sign

1 April 2009

When you build some animations with WPF, Surface or JavaFX you sometimes need to know how evolve an angle. For example, you have the new angle (orientation) of an object and you have store before the last measure of this orientation : how to calculate the evolution ?
calculateAnglesBetweenOrientationExemple1

A first solution

"This is simple" will you say, just do this :

double difference = secondAngle - firstAngle;

But this snippet leads to errors. This is because the orientation value given is relative to a certain initial value, and restart to 0° if you pass the 360°. Lets give you an example: if the object was oriented at 358° and the user turns it of 5° you will obtain a difference of (3-358=) -355° where you actually wants to find 5....

A better solution

A solution I propose is to consider that the methods is called enough frequently that if the object rotate to the left or to the right it has not enough time to rotate more than 180° (half a tour).

Based on this, we consider that the direction of the rotation is given by the "shortest way". If it shorter to turn to the left to go to the new angle, then we select the angle sign which tells we have turned to the left. It may be easiest to understand by looking atentivly to the image above.

An image is maybe better than word : calculateAnglesBetweenOrientationExemple2



We then have this method in C#:

private double calculateDifferenceBetweenAngles(double firstAngle, double secondAngle)
  {
        double difference = secondAngle - firstAngle;
        while (difference < -180) difference += 360;
        while (difference > 180) difference -= 360;
        return difference;
 }


A case of use

When do use it ? For example when you build a carousel: the user can click on a specific item and the carousel rotate so it is in front of you. You then need to have the correct angle. I found no other way to do it.

Does someone have a better way to proceed ?



Shout it
 

Use a screenshot of a WPF visual as a texture in Mogre.

25 March 2009

Hello, Here is my first post about WPF and Mogre, maybe it will helps some people... The subject of today is "How to use a screenshot of a WPF elements and put it as an texture on your Mogre object"...

Why ? Because WPF enable you to create very rich interface and so great image to place on you differents elements...



By the way, I let you follow the link at the end of the post to learn how to blend Mogre in WPF and how to take a screenShot of a WPF visual.

The steps to follow are these :

  1. Create a screenshot of the WPF visual (any visual can be used),
  2. Put the bitmap in a stream and then to a buffer,
  3. Use some unsafe code to create a Mogre MemoryStream and a mogre image,
  4. Use this image to create a texture,
  5. Use this texture in a material,
  6. Put it on the mesh of your choice



Create a screenshot of the WPF visual

The original code is from thomas lebrun and can be found in any good WPF book :

Visual theVisual = this ; //Put the aimed visual here.
double width = Convert.ToDouble(theVisual.GetValue(FrameworkElement.WidthProperty));
double height = Convert.ToDouble(theVisual.GetValue(FrameworkElement.HeightProperty));
if (double.IsNaN(width) || double.IsNaN(height))
{
throw new FormatException("You need to indicate the Width and Height values of the UIElement.");
}
RenderTargetBitmap render = new RenderTargetBitmap(
      Convert.ToInt32(width),
      Convert.ToInt32(this.GetValue(FrameworkElement.HeightProperty)),
      96,
      96,
      PixelFormats.Pbgra32);
// Indicate which control to render in the image
render.Render(this);
Stream oStream = new MemoryStream();
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(render));
encoder.Save(oStream);
oStream.Flush();

Put the bitmap in a stream and then to a buffer

//Back to the start of the stream
 oStream.Position = 0;
 
//read all the stream
BinaryReader oBinaryReader = new BinaryReader(oStream);
byte[] pBuffer = oBinaryReader.ReadBytes((int)oBinaryReader.BaseStream.Length);
oStream.Close(); //No more needed
TextureManager.Singleton.Remove(sName); //Remove eventually texture with the same name

Create the texture

unsafe
         {
            GCHandle handle = GCHandle.Alloc(pBuffer, GCHandleType.Pinned);
            byte* pUnsafeByte = (byte*)handle.AddrOfPinnedObject();
            void* pUnsafeBuffer = (void*)handle.AddrOfPinnedObject();
 
            MemoryDataStream oMemoryStream = new MemoryDataStream(pUnsafeBuffer, (uint)pBuffer.Length);
            DataStreamPtr oPtrDataStream = new DataStreamPtr(oMemoryStream);
            oMogreImage = oMogreImage.Load(oPtrDataStream, "png");
 
            TextureManager.Singleton.LoadImageW(sName, ResourceGroupManager.DEFAULT_RESOURCE_GROUP_NAME, oMogreImage);
 
            //handle.Free();
         }

Use this texture in a material

Here is the code of how you can create a material with this texture:

_dynamicMaterial = MaterialManager.Singleton.Create(SCREENSHOT_MATERIAL_NAME, ResourceGroupManager.DEFAULT_RESOURCE_GROUP_NAME);
Pass pass = _dynamicMaterial.GetTechnique(0).GetPass(0);
 
TextureUnitState tus = pass.CreateTextureUnitState(SCREENSHOT_TEXTURE_NAME);
_dynamicMaterial.GetTechnique(0).GetPass(0).AddTextureUnitState(tus);

Then you just have to use it as a normal texture...

An example:

Here is a little screenshot of the results. I display a cube with the face using as a texture a screenshot of the window in which it is.... WPF screenshot as a texture in Mogre



Link: how to blend Mogre in WPF

page 2 of 2 -