Thursday, March 19, 2009

Announcing the release of our latest Silverlight Toolkit: March 2009 edition.

I just checked when I blogged last and that was in December 2008, when we released the December edition. Since then I have not posted a single thing…  You can be sure that it was because I was hard at work on the toolkit. In it, has gone an enormous amount of work by the team to stabilize code, add new features, provide an actual installer, hugely improve the design time experience using either Blend or Visual Studio and actually create VB samples for our sample app!
If you have SL3 installed, do check out the changelist that has quite a few inline ‘live’ samples.

Also, since you now have SL3 installed anyway, go and look at our sample application, which showcases the controls.

There are six new controls: Accordion, DomainUpDown, LayoutTransformer, TimePicker, TimeUpDown, TransitioningContentControl, and you will be able to blame me for any and all bugs that you find in 5 of those.

(Well, please blame Justin Angel as well, I worked closely with him on these controls and he sure does like it a lot when I share credit).

Let’s take a quick look at my controls. In the coming days, you can expect in-depth posts about all of them. I am planning on going into the design issues as well and am going to point out areas that might change in the future. I’m even going to ‘hint’ at some of the features you just might want to vote on!

DomainUpDown

Live sample here.

This control won’t win the award for being the most creative control in the world, but looks can be deceiving. Think of it as a ComboBox without the popup, and you’ll understand what I mean. A more technical description would be: an UpDown control with an ItemTemplate.

DomainUpDown (DUD) allows you to show a collection of items and iterate over them. It allows you to set an itemtemplate to style them and it features an up and down arrow. Finally, it has an ‘edit’ mode, which will bring you back to a TextBox where you can type.

So, let’s say you have a domain of ‘Red’, ‘Green’ and ‘Blue’, you can visualize these any way you want (using the ItemTemplate) and the user could type ‘Green’ to jump to that item or use the ButtonSpinner to get there.

image

DUD is useful in numerous situations, like in mobile devices but also in visualizing data that you would like the user to ‘browse’ through, such as a slide show.

Accordion

Live sample here.

Accordion is a hugely requested control and I really hope many will find it useful in their day-to-day work. (Please send me samples of how you are using accordion in a creative way!)

An accordion is a control that presents multiple pieces of content and lets the user collapse/expands those. You use accordions everyday, for instance in Outlook.

Highlights of Accordion are:

  • allows multiselection (expanding multiple items)
  • has different selection modes (you can force that a minimum of one item is ‘open’)
  • open/close animation is a VSM state so very easily configured in blend
  • allows sequential animations (say the user selects an item, we will first close the old one and then open the selected item)
  • different expand directions (left/right/up/down)
  • can fill space or take the space it needs

The sample application has a little dashboard that lets you play with different settings.

image

There are a lot of exciting applications for a control like this and I will surely be blogging about Accordion with more details soon.

TimeUpDown

Live sample is here.

A TimeUpDown is TextBox with two spinners, allowing you to use the mouse (or keyboard) to easily set a time.

image

Without a doubt TimeUpDown and it’s friend TimePicker are the most complex controls of the bunch. There is a lot of functionality here that hopefully makes it really easy for end users to select a time.
The big feature is that the controls are completely globalizable, through many extension points. Arabic was easy to implement:
image

Noteworthy features are:

  • contextual spinning: the control is aware of the caret position and will spin accordingly. So you could spin in 10 minute intervals, or in 1 minute intervals, based on the location of the cursor
  • likewise, if you have a defined a minimum or maximum to the control, the possibilities of the spinner are determined by your caret position (you might not be allowed to increment by an hour, although if you move the cursor to the minutes, you can increment minutes still)
  • you can set a culture
  • you can set the TimeFormat used to format the string, as either Short, Long or custom. In the latter case you can define the format your self, the former cases will rely on the defined culture
  • there is a strategy class that handles all the globalization. Almost all methods are protected virtuals, just waiting for you to implement Klingon culture!
  • an extensible TimeParsing mechanism, allowing you to write small parsing classes that make sense in your business. Maybe you want your users to be able to write ‘now’ and have it parse to DateTime.Now?? Can do!
  • out of the box ‘catch-all’ parser, which tries to be as smart as possible when it comes to parsing your time. It allows you to write 1234 and parse it to 12:34. Or 9p and parse to 9:00 PM.
  • intellisense-like experience (balloon) that guides users into entering a correct time

Getting the experience of entering time just right is extremely important to us, so we are actively looking into making the experience even better. The balloon is one of those ideas that I absolutely love. See what I mean:

image

We will hopefully make incremental steps and are actively looking for your feedback.

TimePicker

Live sample is here.

TimePicker uses a TimeUpDown and combines it with the possibility of picking a time through a Popup. We ship with two popups:

The ever useful ListTimePickerPopup:
image

And the often overlooked RangeTimePickerPopup:
image

You can expect us to come up with a few different pickers in the coming releases, but yet again, I would love your feedback on what a good picker is.

The popups can be used as standalone controls as well.

TransitionContentControl

Live sample is here.

This control is in the experimental band. That translates into: don’t touch, just look. The API for this control is most likely going to change significantly. The only reason we publish it, is to get feedback. We want to know if you find these class of controls useful. It is not production quality.

I’ve blogged about the ideas behind this control extensively. A TransitionContentControl can be used as any other ContentControl: it just renders the content you give it to the screen. However, when you set different content to it (it inherits from ContentControl, so just set the Content property, like you are accustomed to), it will not immediately remove the content currently shown on the screen.
Instead, it will start an animation (VSM based) that will transition the ‘old’ content out and the ‘new’ content in. For instance, a fade in/out.

As such, it can be used anywhere where you would normally use a content control.

Most importantly, the API allows you to set the name of the transition you wish to play. So, you might have retemplated the control and added an ‘up’ and ‘down’ vsm state to the presentationgroup. By just setting the Transition property to those names (strings) you can control how the content is transitioned.
So, for instance, a DomainUpDown could use this control and define those states. Then, when the Up button is hit, the Up transition would be triggered. When the Down button is hit, the Down transition would be used.

My team mate Mehdi created some great visual transitions for content and used it in conjunction with the DomainUpDown.

The value of the control is squarely in making it easy for you to drop in a ContentControl that can do transitions, instead of having to write this code by your self again and again.

Warning: Since the control will keep the old element alive in the visual tree for some undetermined amount of time (the time it takes to transition), you should not use the control with UIElements.
That could easily give you a well-deserved exception.

 

More to follow soon!

Thursday, March 19, 2009 9:22:02 AM (Romance Standard Time, UTC+01:00)  #    Comments [32]  |  Trackback
 Tuesday, December 09, 2008

Only a few weeks after our initial release, my team has just released the December edition of the Silverlight Controls Toolkit. Go get it here!

It is a very exciting release because it underlines the teams dedication to releasing fast and often. As you know, the toolkit is licensed under the very permissive Microsoft Public License, which means you can do virtually anything you like to the code. I think with our release schedule, you guys can rest assured that we continue to deliver high quality and very useful controls. In this release we also fixed quite a few bugs, some of which were reported by our users!

One of the most visible controls in the toolkit (autocompletebox) has moved to the stable quality band, as did NumericUpDown. That means the api of those controls is less likely to change, and we are increasingly confident that the controls will address over 90% of customer scenarios.
Ofcourse, many new features were also introduced. Charting has continued to get (much) better, with changes to the way series get instantiated (making it easier on you) and support for multiple axis.
Please check out our improved sample application to see the controls in action.

There is now much better designer integration and 3 new themes were introduced. I love Whistler Blue:

Whistler Blue Thumbnail

I hope you enjoy this release. Please continue your feedback on our forum.

Tuesday, December 09, 2008 11:19:02 PM (Romance Standard Time, UTC+01:00)  #    Comments [12]  |  Trackback
 Wednesday, November 26, 2008

In my previous post, I introduced my thoughts on how animation between positions should be done. Today I will walk you through some of the technical benefits of that approach with a cool animated wrappanel sample. Yes, the silverlight control toolkit includes a wrappanel. Let’s animate it, the easy way!

Sample

I got some feedback that the samples that I inlined were not visible from rss feeds. So, visit this page to see the sample in action.

image

Please note the big black slider on the right.. Drag it to the left to do some layout transitions between items.
Also, to illustrate the flexibility of this approach, there is a textbox on the top that determines the startdelay of the items (Random between 0 and the number you give it). Set it to 700 milliseconds and then quickly drag the slider to the left. You will see some items moving immediately, others moving after some time. This gives it a less ‘plastic-fantastic’ feel.

The items are shown on the page using the xaml below. Notice how I use a regular wrappanel as ItemsPanelTemplate.

        <ItemsControl Grid.Row="1" x:Name="anim" HorizontalAlignment="Left">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <ItemMovementSpike:MoveableItem Margin="10">
                        <Border Background="Yellow" Width="80" Height="80" >
                            <ContentPresenter Content="{Binding}" HorizontalAlignment="Center" VerticalAlignment="Center" />
                        </Border>
                    </ItemMovementSpike:MoveableItem>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <Controls:WrapPanel/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemsSource>
                <Controls:ObjectCollection>
                    <System:String>1</System:String>
                    <System:String>2</System:String>
                    <System:String>3</System:String>
                    <System:String>4</System:String>
                    <System:String>5</System:String>
                    <System:String>6</System:String>
                    <System:String>7</System:String>
                    <System:String>8</System:String>
                    <System:String>9</System:String>
                    <System:String>10</System:String>
                    <System:String>11</System:String>
                    <System:String>12</System:String>
                    <System:String>13</System:String>
                    <System:String>14</System:String>
                </Controls:ObjectCollection>
            </ItemsControl.ItemsSource>
</ItemsControl>

 

Again: who does the animation? Panel or the item

One of the first samples on layout transitions inside a panel are from Dave Relyea (DevDave) and can be seen here. The big difference between the approaches is that he uses a custom-made wrappanel, which does the layout transition.

As you can remember from my previous post, I believe that a panel should only calculate and determine the actual logical position of an item. The transition between positions is not the concern of the panel and should be handled by some other dedicated object. In this case, you can see that I’ve chosen to wrap my content inside of a ‘MoveableItem’ whose concern it is to transition between positions.

As discussed, it is a pity that we have to work so hard inside of MoveableItem, because panels do not notify their children about a position change. But it can be done fairly efficient.

C’mon, isn’t the panel responsible for layout.. So it is HIS concern!

No sir, I strongly disagree. The panel is responsible for the layout of an element on the screen, sure. But they exist in all kinds of forms (Grid, dockpanel, wrappanel) and the intent is to determine the end position as quickly as possible. I feel it is not okay to start mixing that concern with an animation framework.
As always, a class should have only 1 reason to change. A panel should only be changed to alter the layout logic, not because we decided to add features to our transitioning logic.

What are the benefits of separating these concerns

By letting a panel be a panel, and having another class handle the transition, you get a much cleaner model.
First and foremost, we now do not have to alter panels in order to use animation. Most of the solutions I have seen require you to change the baseclass of your panel. This means you can not easily leverage the panels that someone else created, like the toolkits WrapPanel or DockPanel or the build-in Grid and StackPanel! It would mean creating your own versions of these panels. If you’re on the Silverlight side, you may copy our source and change the baseclass, but that will be pretty hard to do for a Grid in any case.

Second, designtime experience. Although I setup my animation in code at this moment, MoveableItem could also just go to a different visual state: ‘Moved’ and allow you to use Blend to create a transition yourself! This would be very easy to do, because MoveableItem could just expose a double where 1 means: in endposition and 0 means: in beginposition. That double could be easily animated using keysplines to create cool effects. See my expander series for more on that approach. I might follow up with a complete sample.

Stretching it a bit, I feel these come into play as well:

Flexibility. I can think of quite a few interesting properties I might want to set on my ‘MoveableItem’, like Weight, Gravity and so on. We could plugin Penner-equations (like, easeIn, bounce etc.) at the item level in a very clean way (cleaner than attached properties).

Performance. The effects I am thinking of go beyond mere transitions. For instance, it might take one item some time to ‘settle-in’: slowly rocking for some time before it finally goes silent. Others might have settled earlier. A panel keeps performing arrange overrides to allow for this. This is overkill.

Conclusion

I find this an intriguing topic. I know people have been using transitioning panels for quite some time now and are very comfortable with it. I hope that this post does make you think though, even though you might completely disagree :)
Let me know either way!

Wednesday, November 26, 2008 9:08:01 PM (Romance Standard Time, UTC+01:00)  #    Comments [8]  |  Trackback
 Sunday, November 23, 2008

In my previous post, we talked about one approach to visualize the change of content. So, we had a control with the content ‘Ruurd’ and when we changed the content to ‘RJ’, we could very easily setup a fade out for ‘Ruurd’ and a fade in for ‘RJ’. Or get more fancy and add a small translate transform.
In this post I want to share some of my thinking on a related subject: how do you visualize the movement of an object? For example: we have a button in a grid on column 0 and we move it to column 1. That move is instant, but in many cases you would like an actual animation between those locations.

There is precedence here, namely in the many tweening libraries for Flash and nowadays for Silverlight. Also, Nikhil has written a lot about this subject with his great attached behavior series.

Sample

I like typing in that textbox a LOT. I’m sure you will too.  :)

Power to the item or does the panel still rule?

It is hard to determine when you should use a panel to do animation and when you should not. I live by this rule:

When the movement itself has meaning, use a panel. If it is an effect, let the item take care of it.

This means: if during the movement you should be able to stop the movement and use the items in that position, than the visual tree should not have any translate transforms going on. The layout system should be managing the location of these items.
If on the other hand the movement is just a transition, the panel should not need to be aware of this transition and just be used to determine the logical positions of an item. That is many times more efficient.

To use examples: a carousel is showing items and we let the user ‘nudge’ the items a few pixels –> the new positions are the real positions and thus a panel should be used.
Items in a dockpanel or a stackpanel that move around within that panel should be managing their transition themselves.

So, I believe effects (visual position) should be managed by the item, logical position should be determined by the panel.

This has the added technical advantage that we do not have to rewrite all panels. This is illustrated by the xaml for this sample:

    <Grid x:Name="LayoutRoot">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <ItemMovementSpike:MoveableItem HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" >
            <Button Click="Button_Click" Content="Move me" />
        </ItemMovementSpike:MoveableItem>
        <ItemMovementSpike:MoveableItem Grid.Row="1" HorizontalContentAlignment="Stretch" >
            <TextBox TextChanged="TextBox_TextChanged" Text="TypeMe" />
        </ItemMovementSpike:MoveableItem>
</Grid>
You can see I just use the regular Grid layout panel, nothing to see there!
Efficient location determination

Because we do not want to change our panels, we will have to determine our position on the screen ourselves. This is a somewhat inefficient process, so it is important to start thinking about where we want to take that hit.

The WPF/Silverlight layout system is very cautious about forcing a layout pass in a panel. It only does so when it is forced, so you can be certain that something has changed. The part of the layout pass that we are interested in is the Arrange part. During the arrange, the panel asks each child to arrange itself given a certain Size and then determines its position. So:

Panel.Arrange
  for each item: Item.Arrange
Panel –> set location and size for item (using a rectangle)

During this time, the most beloved of events is fired continuously on the item: CompositionTarget.Rendering.

The Rending event is called each time before the item is drawn on the screen and therefore comes with great power! If we were to do anything that is using cpu-cycles in this event, we will see some serious performance problems in our application. So, we need to be clever about it.

It is important to know that during the Item.Arrange, our item is still in its old location: The panel has not yet set its position, that will come a few Rendering events later. So, we can use the Item.Arrange to determine the current position with a TransformToVisual call. This is an expensive call, but since we only use it in the Arrange method (which is called only when necessary), it is cheap enough for our purposes.

   78 protected override Size ArrangeOverride(Size finalSize)

   79 {

   80     fromLocation = TransformToVisual(((UIElement) this.Parent)).Transform(new Point(0, 0));

   81     fromLocation.X += tt.X;

   82     moved = true;

   83     return base.ArrangeOverride(finalSize);

   84 }

I determine the current location on line 80 as it relates to its parent (the panel). You could do a quick visual tree walk to find our plugin root, which would enable some cool scenarios!!

Line 81 corrects for our current translatetransform (tt) and then we set a boolean ‘moved’ to true, indicating that something has happened.

The important stuff happens in our Rendering event:

   55 void CompositionTarget_Rendering(object sender, EventArgs e)

   56 {

   57     if(moved)

   58     {

   59         moved = false;

   60         toLocation = TransformToVisual(((UIElement) this.Parent)).Transform(new Point(0, 0));

   61         startmove = DateTime.Now;

   62         moving = true;

   63     }

   64 

   65     if(moving)

   66     {

   67         double fraction = DateTime.Now.Subtract(startmove).TotalMilliseconds/200d;

   68         tt.X = (fromLocation.X - toLocation.X)*(1 - fraction);

   69 

   70         if(fraction >= 1)

   71         {

   72             moving = false;

   73             tt.X = 0;

   74         }

   75     }

   76 }

It happens to be that in the first rendering event that is called, the move has occured. I’m not sure if that is a general rule, or something that just happens consistently on my machine. I haven’t looked into that yet.

We do one more inefficient TransformToVisual to find out where we currently are. Then we need the current time (startMove) and we indicate that we are moving. In the moving code we set the appropriate translateTransform (tt) and make sure that we stop moving when time is up.
If you’re into penner equations, you would plug them in after line 68.

No source for this one though, it’s just a spike. There are many things yet to be considered. But do let me know your thoughts.

Sunday, November 23, 2008 1:58:52 AM (Romance Standard Time, UTC+01:00)  #    Comments [15]  |  Trackback