More servicesWindows Live
HomeHotmailSpacesOneCare
 
MSN
Sign in
 
 
Spaces home  Joe BlogsProfileFriendsBlogMore Tools Explore the Spaces community

Joe Blogs

March 12

Mix 08 Sessions RSS Feed with WMV Enclosures

I couldn't find this anywhere, so I put it together myself from a links page.  This is all 80 (or so) session videos from Mix 2008 with enclosures for the WMV files.  Should work in the Zune desktop client or iTunes etc.

Mix 08 Sessions WMVs

Technorati Tags: ,,
January 03

WPF ItemsControl Virtualization and Fast Moving Data Sets

As some have commented, GUI object virtualization is an important part of WPF.  It allows WPF to only create a small subset of UI element objects when binding to a much larger set of data objects.  The subset usually relates to the elements visible on the screen.  These UI objects can also be reused as the user scrolls through a large data set, reducing pressure on the garbage collector.  This post covers a WPF sample demonstrating the behavior of the ItemsControl and looks at the possibility of using UI virtualization to optimize model/view updates for a fast moving data set.

In the finance industry data objects can be updating very quickly.  It's common to have a data set of around 3000 objects updating at over 7000 times per second.  The challenge is to efficiently update the data model without impairing the user experience.  Sometimes it's possible to throttle updates to the client process through an intermediary server, but in some cases these updates need to be real-time. 

One technique used when binding to a fast moving data model is to avoid sending update events if the data is not visible - i.e. there are no visible UI elements hooked up to the data.   A possible way of detecting if a data object is being viewed is if the INotifyPropertyChanged PropertyChanged event has been wired up or not.  If an ItemsControl is bound to a collection of data objects supporting this interface the virtualization of the UI objects will cause this event to be hooked and unhooked depending if the data is being displayed or not.  In theory, a fast moving data set could simply use the status of the event on the INotifyPropertyChanged interface to test if it needs to notify the presentation tier that data has changed.  Realistically, this technique needs to be used with other optimizations such as conflating and queuing the data updates.  But having an effective 'I am being observed' flag would be really useful way of optimizing the protocol between the model and the view.

To demonstrate the behavior and test the usefulness of using this event I've posted a small sample application.  This shows a ListBox bound to 1000 items (of type MyObject).  The MyObject class contains a static property - a separate collection that represents the INotifyPropertyChanged.PropertyChanged event's hooked status.  The MyObject catches hooking and unhooking this event and updates the HookStatus collection.

The ListBox is bound to the MyObject collection so that we can test the behavior of the ItemsControl and how it hooks and unhooks the MyObject class as the virtual UI objects are created and reused.  A custom ItemsControl is used to show the separate hooked status collection.  This ItemsControl is bound to the HookedStatusCollection and simply shows a red pixel if the MyObject is hooked up, and an empty pixel if it's not.  The 1000 element collection is represented by the 1000 pixels across the top of the window.  The project is linked below (VS2008, .NET 3.5 binary included).

As can be seen by running the application the ItemsControl is very generous when it comes to creating UI objects.  It's very easy to scroll through the ListView and hook up nearly all the observed objects.  This means that using the state of this event is not a good indicator of the visibility of the data.  I need to investigate a little further to see how much code is executed if an invisible UI object receives a update event from its sourced object.  The overhead may be minimal, but avoiding invoking the event at all would be better.

Ideally this behavior should be configurable.  In some cases it makes sense to be more conservative with UI objects, especially when the cost of keeping these objects is more than the memory that they use.  If there was a way of setting guideline parameters for the maximum number of UI objects that an ItemsControl should maintain then we could optimize some lists for showing real-time data updates. 

November 09

Animating Layout in an ItemsControls

Last year Karsten Januszewski posted a blog entry about 'layout to layout animation' called Phenomenological Layout.  In his code he took a background Panel and replicated the positions of elements onto a Canvas.  On this canvas he was able to apply animations and reuse whatever Panel the developer decides is best for their layout.

I wanted to use a similar idea but focus on an ItemsControl as the basis of the animation.  I also wanted to try to hookup the LayoutUpdated event to efficiently set-up and animate each element.  The idea here is that I have a databound ItemsControl that animates as the layout changes, using whatever layout schema I want.  Even a re-sort of the elements in the ItemsControl should animate the elements into the correct order.

The problem with the layout engine that the Panel classes provide is that it's very difficult to hook-up events to find out what the Panel is doing.  The behavior isn't easily observable in that there's no simple event providing the child element, the old location/size and the new location/size.  If the base Panel class had this event then layout to layout animation would be so easy - it could even be done through XAML and Expression Blend.

The solution that I opted for adds this functionality by way of a utility class that is pretty easy to call from a custom ItemsControl.  The LayoutUpdated event is hooked up using a surrogate object and the derived ItemsControl holds a reference to a container of these surrogates.  When items are added to the ItemsControl (seen below using the PrepareContainerForItemOverride virtual function) the Items control calls out to the container and hooks up the Layout event so the surrogate can do something when its being resized or repositioned.

protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
    base.PrepareContainerForItemOverride(element, item);
    this.container.Add( new Surrogate( this, element, item ));
}

The surrogate object uses the LayoutUpdated event of the new element and wires up its own event handler. The big problem with this event is that it doesn't come with any indication what is being updated, by who and to where.  So I use the surrogate to keep hold of this information.  The wire up process on the surrogate object looks like this from the constructor:

public Surrogate(ItemsControl itemsControl, DependentObject element, object item )
{
     :: ::
     element.LayoutUpdated += new EventHandler(this.target_LayoutUpdated);
     if (this.element.RenderTransform == null || !(this.element.RenderTransform is TranslateTransform))
     {
         this.element.RenderTransform = new TranslateTransform(); // setup render transform
     }
:: :: // etc }

Now everything is wired up it's simply a matter of setting the animation in motion when a layout even has changed:

public void target_LayoutUpdated(object sender, EventArgs e)
{
    ::
    // get new position of element
    Point newPosition = this.Element.TranslatePoint(new Point(0, 0), this.Container.animatedItemsControl as ItemsControl);
    TranslateTransform translateTransform = this.Element.RenderTransform as TranslateTransform;
    // offset this position of the current render Transform offset
    newPosition = new Point(newPosition.X - translateTransform.X, newPosition.Y - translateTransform.Y);
    // check for rounding errors
    Point deltaToOldPosition = new Point(this.Destination.X - newPosition.X, this.Destination.Y - newPosition.Y);
    if (Math.Abs(deltaToOldPosition.X) < 1 && Math.Abs(deltaToOldPosition.Y) < 1)
    {
        return; // nothing to do
    }
// we now have the new and old positions - so animate the render transform from where it was to zero
// because the element has already been repositioned
translateTransform.BeginAnimation(TranslateTransform.XProperty, new DoubleAnimation(deltaToOldPosition.X, 0.0, new Duration(animationTime), FillBehavior.HoldEnd)); translateTransform.BeginAnimation(TranslateTransform.YProperty, new DoubleAnimation(deltaToOldPosition.Y, 0.0, new Duration(animationTime), FillBehavior.HoldEnd)); :: :: // etc }

This isn't the exact code, but the key points are here.  The same adjustment can also be used for the size transformation - the process is the same by using the delta from the old size to the new size to feed into the render transformation.   The elements themselves can be recycled through the ItemsControl so it's important to unwire the association between the object and the element using the ClearElement override.

This all gives the necessary functionality to animate elements off the back of the mysterious LayoutUpdated event by giving it some context.  As a byproduct we also have the current location of any child element given the bound object that is being templated in the ItemsControl.  With this we can now build a generic ItemsControl that throws RoutedEvents for layout changes that can be used with Triggers in animation and even animate between ItemsControls by looking up the location of a bound object.

Technorati Tags: ,,
November 07

Zune Firmware Update - rating feature reduced

Technorati Tags: ,
Zune Insider reported yesterday that the new Zune firmware removes the regular 5 star rating system and replaces it with a 'good' or 'bad' rating system.  This means we've gone from 5 levels to just two.  The reason for the removal of this feature is to make it simpler and add more parity across users ratings - I assume, so that ratings can be aggregated and reported through some social website.
 
This argument doesn't really stand, as the same parity issues still apply.  What is defined as Good and Bad for users?  Some users may download their favorite tunes and only rate 10% as Good.  Other users may download lots of tracks and mark most of it as good.  When aggregating ratings there will be nothing to distinguish an excellent track from a quite good track. 
 
The real problem, though, is the downgraded functionality.  Like a lot of users, I use ratings to set-up automatic playlists based on genre and artist.  I also use ratings as a way to filter through mass downloaded subscription music.  I flag the music that I want to delete with a '1 star rating'. 
 
Even more of a problem is the migration process.  The upgrade will automatically map any track >2 stars to be good and all others as bad.  What isn't clear is how the new rating system will be managed?  How will these ratings be stored?  At the moment the Zune software uses the track itself.  There could be some very unhappy audiophiles with lost track ratings next week if the upgrade decides to update the song files with its new scoring mechanism.
 

Xbox Live GamerCard

joeywood
Xbox Live GamerCard
Reputation:
Reputation:Reputation:Reputation:Reputation:Reputation:
Score:
840
Zone:
Recreation
Hexic 2Call of Duty 4Sealife SafariViva PiñataLEGO Star Wars II

Xbox Live Recent Games

Hexic 2
Achieve:
6/12
Score:
55/200
Call of Duty 4
Achieve:
2/37
Score:
40/1000
Sealife Safari
Achieve:
1/12
Score:
5/200
Viva Piñata
Achieve:
3/50
Score:
60/1000
LEGO Star Wars II
Achieve:
1/29
Score:
20/1000