Archive for the ‘Silverlight’ category

Silverlight: Framework vs API

March 11th, 2009

I have been developing a new Silverlight framework for the last two months.  Well, really just the last month since it took my about a month to actually ramp up to a point where I felt comfortable writing a Silverlight framework.  The reason I am writing a Silverlight framework in the first place is that we intend on using Silverlight to enhance some of the advanced features of our our existing web apps, and perhaps to develop a new web app.  Our stuff is written in ASP.Net, so it made sense to go with other .Net-based tech.

I decided that we needed to write  a framework around the time we first decided to start looking into Silverlight.  There are a lot of custom things we do in our existing ASP.Net framework, and some of that would need to be replicated for Silverlight.  When I started down this road I did not imagine I would have as much work to do as I have done.  I was actually counting on a lot of stuff in Silvelight to be extensible that is actually not extensible.  I am learning that Silverlight acts more like an API than a Framework.

Consider the Timeline class.  This is the class on which multiple animations classes are based.  Storyboard, DoubleAnimation and ColorAnimation are three common classes that derive from Timeline.  Since .Net (in general) is a framework and not an API (although it contains numerous APIs) I figured I would be able to derive from Timeline to create my own, custom animation classes.  This is a common task in normal .Net land.  Many core-framework classes are written to be extensible.  Boy was I stupid for thinking such a thing about Silverlight’s Timeline class!  As it turns out extending Timeline gets you nowhere.  The Timeline class, and the classes that derive from it in Silverlight, do not contain any actual animation logic.  They are really just command objects that describe some values about a particular type of animation, and the animation itself is run deep in the Silverlight runtime.

This really doesn’t do me any good for a couple of the tasks I would like to accomplish.  The recommendations online are either to use a timer or use a thread to drive a “game loop” to do custom animations.  Really?

So this morning I set out to write a custom animation framework.  I had been thinking of this for a while, so perhaps I should admit that I started the thought experiment of “How do I write a custom animation framework in Silverlight?” a couple of weeks ago.  Still, I wrote my first line of code this morning shortly after 9:00 AM CST.  At around 4:30 PM CST I had checked in an abstract classes similar in purpose to Timeline, except it actually drives the animation.  I had further derived an abstract child for animations that target object properties for animations (most cases), a class to extend said object that animates doubles (think DoubleAnimation), a concrete child that groups animations (think Storyboard), and a class that allows the programmer to write a custom logic that is fired for every frame render.  My core logic is based on the DispatchTimer class (in System.Windows.Threading), which I chose because it does the cross-thread invocation for me.

I am still missing some of the functionality that is represented in the Silverlight counterparts, and am missing several types of animations.  Additional animations should be easy to implement now that I have the base stuff written.  It should be really easy to replicate those classes found in the Silvelight version of .Net as most of those are really just numeric range animations.  I also need to implement some functionality like AutoReverse, and looping logic for my own Storyboard object (which is called GroupStory).  What does it do when all of its animations are complete?  Repeat?  And the framed animations are also a task to get to in the near future.

I did all this work, it is tested and checked in, in one day.  I wrote a framework to replace an API.  As much as I like Silverlight 2.0, I wish they have waited just a little longer to get some more of these “framework vs API” things resolved.  Animation is just one of the examples of where Microsoft should have been thinking about how all of us software engineer types in the real world would be extending their functionality.  But its a big example, especially considering their target audience.  I am not kidding myself here.  I prolly have bugs waiting for me in that code.  But I can leverage it to do so many interesting things now.  It may take me the rest of the week to really work through the other animations and fix bugs.  Maybe I will still be working on it next week.  But I am just one guy, and I can accomplish this much in such a short period of time?

I am also not kidding myself about the talent at MS.  IMO, .Net is Microsoft’s nicest product.  They have done a stellar job with it.  C# is my favorite language.  And really, Silverlight is a wonderful run-time.  I have no doubt that those developers and managers at MS responsible for it are hard working and talented people.  I just hope that the next version of Silverlight they produce is more like a framework that the current version.

Custom Visual States in Silverlight

March 9th, 2009

Visual States are the way Silverlight communicates basic state information about an object.  Is a button pressed?  Is a mouse over a button?  Is a button normal?  The available states for an object are indicated via decoration with the TemplateVisualStateAttribute (in System.Windows).  For example, the Button class in Silverlight looks like this:

[TemplateVisualState(Name="Unfocused", GroupName="FocusStates"),
TemplateVisualState(Name="MouseOver", GroupName="CommonStates"),
TemplateVisualState(Name="Normal", GroupName="CommonStates"),
TemplateVisualState(Name="Pressed", GroupName="CommonStates"),
TemplateVisualState(Name="Disabled", GroupName="CommonStates"),
TemplateVisualState(Name="Focused", GroupName="FocusStates")]
public class Button : ButtonBase
{
    // Methods
    public Button();
    internal override void ChangeVisualState(bool useTransitions);
    public override void OnApplyTemplate();
    protected override void OnClick();
    protected override AutomationPeer OnCreateAutomationPeer();
}

You might notice from this code that the various states also have group names.  If you look at the states it makes sense why we would want to group them.  States like Unfocused and Focused are related.  States like Mouse Over, Normal, Pressed, and Disabled are all related to how a button looks with various interactions.  Silverlight only allows one state from any group of an object to be active at once.  This also makes sense.  A button cannot be Focused and Unfocused, or Pressed and Normal, but a button can be both Pressed and Focused.  I like to think of each group like an enumeration, and the states of each group as the values that enumeration can hold.

When the button switches to a new state, it does so by calling VisualStateManager.GoToState(…).  Of course there needs to be some logic to fire this switch, and this is ultimately driven by built-in events like MouseEnter, MouseDown, etc.  To switch to Focused, the code might look like:

VisualStateManager.GoToState(this, "Focused", true);

To consume visual states one uses something called a VisualStateGroup class which contains a VisualState objects, one each corresponding to a visual state decorated on the class. This object is attached to the object’s template. Here is some sample XAML for the button class:

<ControlTemplate TargetType="Button"
                 xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows">
  <Grid >
    <vsm:VisualStateManager.VisualStateGroups>
      <vsm:VisualStateGroup x:Name="CommonStates">

        <vsm:VisualStateGroup.Transitions>

          <!--Take one half second to trasition to the MouseOver state.-->
          <vsm:VisualTransition To="MouseOver"
                              GeneratedDuration="0:0:0.5"/>
        </vsm:VisualStateGroup.Transitions>

        <vsm:VisualState x:Name="Normal" />

        <!--Change the SolidColorBrush, ButtonBrush, to red when the
            mouse is over the button.-->
        <vsm:VisualState x:Name="MouseOver">
          <Storyboard>
            <ColorAnimation Storyboard.TargetName="ButtonBrush"
                            Storyboard.TargetProperty="Color" To="Red" />
          </Storyboard>
        </vsm:VisualState>
      </vsm:VisualStateGroup>
    </vsm:VisualStateManager.VisualStateGroups>
    <Grid.Background>
      <SolidColorBrush x:Name="ButtonBrush" Color="Green"/>
    </Grid.Background>
  </Grid>

This markup generates a VisualStateGroup named to correspond to a group on the object. It contains visual states, each named to correspond to an existing state on the object.  The VisualStateGroup can also contain transition objects to control the transition to any given state.  The VisualState itself doesn’t do anything but start a Storyboard animation.  From that animation you target objects and properties as you would any other story board.  The pieces all just fall into place!

Many built-in object contain a number of visual states that you can utilize with control templates to change look and feel, but you can also create your own visual states on custom objects, and consume those states in your own custom code.  While this system is not as flexible as the event triggers built into WPF, it does allow for some interesting capabilities.

Determining If Rectangles Intersect?

March 5th, 2009

Its funny the things one finds out are missing in a new framework.  Silverlight 2 is missing (as far as I can tell) a rectangle intersection/collision/overlapping test function.  I started writing my own and immediatly had a very nasty chunk of code.  I knew I was doing something wrong.  I found this short article which immediatly made me think back to college CompSci with its simple solution.  I need to test if two rectangles are overlapping, but the logic is easier if I write to test if they aren’t overlapping and negate the answer.  I have written an extension method in C# for the Silverlight Rect class to impliment logic similar to this.  Nifty!

Silverlight 2 1/2

March 3rd, 2009

There are some missing parts to Silverlight that really bother me.

  1. TemplateBinding – The TemplateBinding concept is a XAML tag only.  There is no backing class in the CLR.  Additionally, the TemplateBinding functionality does not support complex paths.
  2. Control Binding – There is no control binding is Silverlight.  Databinding works great, but I sure would like to be able to bind to a dependency object.
  3. ControlTemplate – You cannot programatically construct a ControlTemplate.  The ControlTemplate is both a XAML tag and a class, but there are no properties or methods in the class to provide a way to construct it in code.  This is yet another case of the XAML parser and the Core CLR doing some black magic.
  4. Timeline – The Timeline class is the base class for all of the built-in animations in Silverlight like Storyboard, ColorAnimation, DoubleAnimation, et al.  With a base class like this one would think one could inherit and implement a custom animation class.  Nope.  It looks like the actual functionality for these animations is hidden somewhere in the Core CLR, and these classes are just definitions of the animation.  To do custom animations one must use a game-loop.

These are all “black box” items to me.  Each one of these items bothers me because it presents Silverlight not as an extensible framework but as a simple API (well, not so simple).  As a long time .Net developer this really bothers me.

A couple of other things that bother me about Silverlight:

  1. Graphical elements do not have a “position changed” event.  Sometimes I want to know if an element has moved so I can do something about it.
  2. No right-mouse button support.  There are hacks to get around this but they don’t necessarily work across browser.
  3. Built-in drag-and-drop.  I just finished writing a custom control to allow drag-and-drop.  It was a lot of work and is not fully featured.

Point #2 from above is an inconvenience, but point #1 makes me take some radical approaches like polling or writing custom objects that do attempt to tell you when they have been moved.

With all of this hasle, Silverlight is a quantum-leap beyond HTML + CSS + Javascript.  It downloads and installs quickly.  It is very responsive.  The graphical things it can do are very awesome.  I just hope Microsoft address some of these points in the next release of Silverlight.

Poor Silverlight Documentation

February 17th, 2009

Microsoft has done a rather poor job of properly documenting Silverlight 2.0. I have run across several outright errors in the official MSDN documentation, and finding acurate documentation at other sources is very difficult. Today I am trying to style the header elements of a Silverlight DataGrid. The documentation for this is scant and wrong. Luckily I have found the default styles used out-of-the-box by Silverlight. Using the default styles, I figured out exactly where I was going wrong, and where various documentation I had read was wrong. There is nothing like learning by example.

Silverlight Toolkit and Developing Silverlight Controls

February 14th, 2009

I have been spending a significant amount of time in Silverlight lately.  Silverlight is very young.  The base technology is solid but it is not as featured as more mature web technologies like ASP.Net.  Being young also means that there are not a lot of 3rd party libraries available for a variety of tasks.  So I have been writing a lot of framework and component code for our prototype (and possibly production) code.

After a few attempts at developing a clean user control for what should have been something that is very simple, are started looking at the Silverlight Toolkit source code to see if I could garner any best practices from the work Microsoft is doing.

The Silverlight Toolkit team has done some interesting work setting up their project.  Instead of developing the toolkit controls with the standard UserControl base class, they have instead opted to write classes based on ContentControl and other base classes.  To pair up XAML with the “code behind” they did something really interesting.  They engineered a pre-compile task to take XAML resource dictionaries and combine them into one resource dictionary for the project, the so called “generic.xaml” dictionary that provides styles and templates to control libraries (think DLL).  I won’t go into a thorough explanation on this page (though I do explain the basic below), but I would invite you to check out the source code and take a look at the explanation of how it all worked here.

It really cleaned up my code.  The Silverlight Toolkit approach eliminates a lot of C# code and replaces it with declarative markup.  This is a good thing because C# code can have bugs, where declarative markup usually works or it doesn’t.  One must test for edge cases in C#, markup usually works or it doesn’t.  Get get the picture.  That, and for my specific cases it eliminated some really horrible code patterns.  The patterns are much simpler now:

  1. Write dependency properties and their associated ROC (Regular Old Class) properties to represent various items that need to be represented or displayed in UI.  For example, child components, styles, colors, brushes, text, etc, would all be loaded into DPs.
  2. Initialize DPs through ROCs in the control constructor with the default values.
  3. Set the DefaultStyleKey of the control to the type of the control.
  4. Template the control with a style/control template combo in a resource dictionary that will get compiled into the DLL.  The Style will be wired up to the control because the TargetType is used as the default style key set in #3.  Use the TemplateBinding XAML markup to bind the the DPs.
  5. Rinse, repeat.

The first controls I developed were with the traditionaly “Silverlight User Control” template were full of spaghettie code trying to manage child controls.  Since then I have used the Silverlight Toolkit approach, and I have been writing much better code.

ContentPropertyAttribute

February 9th, 2009

While diving into the programming of custom controls in Silverlight I wanted to set one of my properties as the “default property” from XAML.  What I mean here is that I wanted to emulate the behavior of many out-of-the-box controls in Silverlight (and WPF for that matter) where a property need not be explicitly specified, in all cases a content property of some sort.  For example, the Button control has a Content property which can be set in these three ways (excluding binding):

  1. <Button Content=”Click Me”/>
  2. <Button><Button.Content>Click Me</Button.Content></Button>
  3. <Button>Click Me</Button>

The relationship between these different ways of setting Button.Content should be fairly obvious.  Through XAML one can usually set any property on the underlying object via an attribute or child element.  Additionally, one property can be marked as the “default property”.  But how is this done?  How can I write a control and mark one of the properties as the “default property”.

In XAML/Silverlight/WPF parlance, this is refered to as the Content Property, which is confusing since there is also a property on a number of controls called content, and to make it even more confusing the property named Content is also the Content Property.  Confused?  Lets take a swing at this using my custom control and see how to set the Content Property on a control with no property called Content.

I have a control that doesn’t have “content” per se, but accepts a list of rules which regulate how the control should act.  I want the XAML to accept this list as the “default property”.  I want to be able to write:

<RuleManager>
  <Rule ... />
  <Rule ... />
  <Rule ... />
</RuleManager>

instead of the more verbose:

<RuleManager>
  <RuleManager.Rules>
    <Rule ... />
    <Rule ... />
    <Rule ... />
  </RuleManager.Rules>
</RuleManager>

The way I do this is with the ContentProperty Attribute in System.Windows.Markup:

[ContentPropertyAttribute("Rules")]
public class RuleManager
{

public static readonly DependencyProperty RulesProperty =
DependencyProperty.Register(“Rules”,
typeof(RulesCollection),
typeof(RuleManager),
new PropertyMetadata(null));

public RulesCollection Rules
{
get { return (RulesCollection)GetValue(RulesProperty); }
private set { SetValue(RulesProperty, value); }
}

public RuleManager()
{
Rules = new RulesCollection();
}
}

The ContentPropertyAttribute class should probably be renamed something like DefaultXamlPropertyAttribute since it does not always specify Content, but does specify the default property.  Its constructor takes the name of the property to use as the default (or "content") property. It took some digging, but this is the correct way to do it and it is tested working.  From XAML I need not specify the Rules element (aka property); the XAML parse will assume that information included here is mean for the Rules property based on the attribute.

MSDN documentation of ContentPropertyAtrtibute in Core CLR (Silverlight)