February 2006 - Posts

WPF - local animations (animations in code)
02-28-2006 4:57 PM

When trying to animate a WPF object in code (this is called a local animation) you sometimes need to be careful about which property you need to feed to which class. At the current (Februari) CTP timeframe the documentation isn't really clear on this but I am sure this will be fixed by the time WPF goes gold.

In my situation I had a rectangle inside a canvas whose location I wanted to animate. The caveat is that the location isn't a property of a rectangle itself but instead an attached property on the canvas containing the rectangle.

The proper way to do a local animation is to create a storyboard object and animate the properties by using the TypeAnimation objects like this:

Storyboard sb = new Storyboard();

Duration
duration = new Duration(TimeSpan.FromSeconds(0.2));

DoubleAnimation
da1 = new DoubleAnimation(x, duration);
DoubleAnimation da2 = new DoubleAnimation(y, duration);

The next step is to specifiy the target of your animation. This needs to be our rectangle, since that's the object that will be the target of our animation (even if the actual properties being animated are attached by the canvas!):

Storyboard.SetTargetName(da1, rectangle.Name);
Storyboard.SetTargetName(da2, rectangle.Name);

Do make sure that when creating the rectangle it has a valid name, this is required to do local animations.

The next step is where it gets tricky (well not really tricky, but it did require some experimenting). I said before that the left and top property are not really on the rectangle but rather attached through the canvas, so we need to tell the storyboard about this:

Storyboard.SetTargetProperty(da1, new PropertyPath(Canvas.LeftProperty));
Storyboard.SetTargetProperty(da2, new PropertyPath(Canvas.TopProperty));

The very last thing to do is to add the two doubleanimation objects to the storyboard and signal it to start.

sb.Children.Add(da1);
sb.Children.Add(da2);

sb.Begin(canvas);

I hope this made since.

by Waseem Sadiq | 2 comment(s)
Filed under:
WPF - custom types and polymorphism
02-28-2006 4:32 PM

I was working on a WPF application and needed to do a complex rectangle-like UI element. Hey custom styles is what WPF is good at right? To be quite exact I needed a custom control template, since I couldn't style a rectangle the way I wanted to.

I decided to use a System.Windows.Control (which isn't sealed, a rectangle is) and inherit from this in order to add some custom behavior. I created a custom template by creating a control template element inside my Window.Resources section like this:

<ControlTemplate x:Key="ControlTemplate" TargetType="{x:Type Control}">...</ControlTemplate>

This works just fine as long as long as your custom class acts like a control. The moment you try to bind to a custom dependancy property like this (in which Title is our custom dependancy property):

<TextBlock Text="{TemplateBinding Property=Title}" />

You get the error message "Cannot convert the string 'Title' into an object of type 'System.Windows.DependencyProperty'. The result is 'null', which is not an allowable value.."

This actually is completely logical since you told the control template that you would be feeding it a System.Windows.Control but instead you are feeding it your own custom type which inherits from System.Windows.Control.

The right way to do this is to reference your type using the clr-namspace mapping syntax and changing your control template decleration like the following:

<ControlTemplate x:Key="ControlTemplate" TargetType="{x:Type YourCustomControl}">...</ControlTemplate>

Although this sounds logical it did keep me busy a while. Perhaps the WPF folks want to do some less-cryptic error message on this one.

Hope this helps out somebody.

by Waseem Sadiq | 1 comment(s)
Filed under: