Thursday, January 29, 2009

Getting Professional Quality Animations with the KeySpline Editor in Expression Blend

When I first started working with WPF and Silverlight, I was amazed at how simple it was to create animations, especially when using Expression Blend. I was always frustrated with one thing though... they just didn't look very professional. I could edit the speed of my animations, but the interpolation of the values in the animation was always linear. That is, if I had an animation that changed a button from size 1px to size 10 px, which lasted 10 seconds, it would cause the button to change at a rate of 1 px per second. This linear interpolation frustrated me. I wanted some of my animations to ease in, or ease out. For instance, when I Show a pop-out panel, I typically like to make the animation occur really fast at first, and then slow down towards the end. Like in the button example, I would like the button to grow to 8 px in the first 3 seconds, and grow from 8 px to 10 pix in the last 7 seconds. This tends to make the animations look more professional.

So... how do you do it?

First, create your animation in Blend. Once you have your animation (storyboard) created, you should see something like this in your Objects and Timeline panel. In this example, I have applied an animation to a grid named grdSelectDate which takes 1 second to complete. This is indicated by the little egg-shaped dot placed in the timeline next to the grdSelectDate grid.

image

If you click on this dot, it will change colors from white to gray. This now gives you the ability to use the KeySpline editor.

image

You can see the editor under the Properties tab. You can think of this editor like this. The X axis represents the value of the affected property. In my example, it would represent the size of my button (this is a made up example... the size would actually be two different properties.... height and width or a single scaleTransform property... you get the idea though!). When X = 0, the value is at it's original state, so the size of my button has not changed, when X = 1 (top of the scale), the value has now reached it's final value (10 px in my fictional example). The Y axis is a function of time. Y=0 is the start of your storyboard and Y=1 represents the end of the storyboard (10 seconds in my button example).

To edit these values, you can simply click and drag on the yellow dots or enter values in the textboxes below(not as easy...) to change the speed of easing in/out of your animations. In this example, the animation starts really quickly (indicated by the steep incline of the line) and then slows down towards the end (indicated by the very small change in the x value while the y value keeps changing).

image

Keep playing around with this graph to ease in and out and you will see your WPF and Silverlight applications kicking it up a notch in no time!

Monday, January 19, 2009

Presidential Swearing-In Ceremony On Silverlight

http://www.pic2009.org/blog/entry/watch_the_swearing-in_ceremony_on_the_web/

image 

Yeah. I think Silverlight has caught on fairly well. If you are considering Silverlight but are wondering if the adoption rate is an issue, consider this. Many big players including NBC Olympics, Netflix, AOL, and now the Presidential Inaugural Committee. Yeah... I think it's safe to say Silverlight is here to stay. Watch out Flash!

Thursday, January 15, 2009

Silverlight Tip: Give Your Silverlight App Focus

I am working on a Silverlight application that starts off with a login page. Typically, users do not like to use the mouse when they get to a login page. They expect to go to the page, type their user name, tab, type their password, click return and they should be logged in. In order to get this type of behavior in a Silverlight application, you need to set the tab order of your fields, set the focus to the username textbox and also set the focus to your Silverlight app (remember... this is content inside of an aspx page.. or an htm page). To give the Silverlight content focus, simply make this call:

HtmlPage.Plugin.Focus();


Then, give the username textbox focus and you should be set to go. One other thing... if you want users to be able to hit the return key immediately after typing their password, you will have to check for the return key in the text changed event handler of the password textbox. If the enter key is detected, then you can attempt to login at that time. If you do not do this, you will force your users to tab to the login button and then hit return. This just saves them a few clicks.

Friday, January 9, 2009

Weird Silverlight Bug!

Ok. This is a weird one. It had been causing problems in one of my apps for a very long time, and it was making me very frustrated... so I decided to hunt this one down. Anyway.. Last night, I figured it out.

Tablet Pc + Listboxes inside Tab Panels = CRASH!

 

This doesn't make too much sense, so let me explain. Listboxes work great in Silverlight. Tab controls work great as well. If you have a listbox in one of the TabPanels it works great as well. If you do this in a Tablet PC (Vista... XP works fine... Go figure!), things are not so good. I built this little app just to verify my find. It consists of a simple TabControl with two tabs. The first tab has a listbox with three items. the second tab has a button.

<UserControl x:Class="TestSlTabletPcBug.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:tools="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls">
<
Grid x:Name="LayoutRoot" Background="White">
<
tools:TabControl Height="300" Width="500">
<
tools:TabItem Header="list">
<
ListBox>
<
ListBoxItem Content="1"/>
<
ListBoxItem Content="2"/>
<
ListBoxItem Content="3"/>
</
ListBox>
</
tools:TabItem>
<
tools:TabItem Header="button">
<
Button Content="hi"/>
</
tools:TabItem>
</
tools:TabControl>

</
Grid>
</
UserControl>



image



I do not have a tablet pc, but I do have a Tooya tablet. When this tablet is not plugged in, the application works fine. I can select any item in the listbox and switch between tabs. As soon as I plug my tablet in it doesn't behave as nicely. If there is any item on the listbox, I can't switch tabs. If I do, the application crashes and IE shuts down. Weird!



The workaround....



My workaround was easy... unplug the Tooya tablet and then it worked fine. If you are running on an actual Tablet Pc, simply go to the list of services and stop the Tablet Pc Input Service. Once this is stopped, the application should work fine.



Well... there it is. Hopefully this will save some of you some frustration.

Tuesday, January 6, 2009

Detecting a Double Click in Silverlight 2

Nope! It's not supported. In Silverlight 2, you can only detect single clicks. So... here's a way of faking it.

First of all, you are going to need an integer variable indicating how much time between two consecutive clicks constitute a double click. In this example, I am setting it to 175 milliseconds.

private const int DOUBLE_CLICK_TIME = 175;  // milliseconds between MouseUp and subsequent MouseDown


Next, you will need a DateTime variable to store the time of the last MouseLeftButtonUp event. Initially, you can set this to DateTime.MinValue.



private DateTime _lastTimeClicked = DateTime.MinValue;


Next, you will need to assign event handlers for your object's MouseLeftButtonDown and MouseLeftButtonUp events. In this case, I want to detect the double click on an object named LayoutPanel.



this.LayoutPanel.MouseLeftButtonDown += new MouseButtonEventHandler(LayoutRoot_MouseLeftButtonDown);
this.LayoutPanel.MouseLeftButtonUp += new MouseButtonEventHandler(LayoutRoot_MouseLeftButtonUp);


Now implement the event handlers. In the Button Up event handler simply store the current time as the last time clicked. Then in the down event handler call the IsDoubleClicked Method.



void LayoutRoot_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
_lastTimeClicked = DateTime.Now;
}

void LayoutRoot_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (IsDoubleClick())
{
//Double Click Logic Here
}
}


Finally, implement the IsDoubleClick event. This method returns true if there has been a double click, and false if not. It simply measures the current time agains the time last clicked. If the elapsed time between the two is less than the time specified in the DOUBLE_CLICK_TIME constant previously defined, it returns true... indicating a double click.




private bool IsDoubleClick()
{
TimeSpan elapsed = DateTime.Now.Subtract(this._lastTimeClicked);
return elapsed.TotalMilliseconds < DOUBLE_CLICK_TIME;
}



So that's it. As with some of my other posts, I hope this information will become useless soon because it gets included in a future release of Silverlight, but in the mean time, you can use this simple workaround to get the double click functionality into your Silverlight applications.