WPF 4.5 New Feature: Live Shaping

October 2, 2011

tags: , , , ,
2 comments

The BUILD conference concentrated on the new Windows Runtime (WinRT) component of Windows 8, but .NET 4.5 was also introduced, providing enhancements and new features. WPF & Silverlight seemed to have suffered a blow (some would say a knockout), as the new Windows 8 “Metro” model is not built on the same types, but rather wraps new native C++/COM libraries (that’s WinRT for you). Still, line of business applications will not be “Metro” anytime soon, so I think saying goodbye to WPF is premature.

There are some new features in the preview of WPF 4.5, one of which is really nice, called Live Shaping.

When you bind a collection to a ItemsControl, you can do so indirectly, through a view (with the ICollectionView interface, for example). This allows sorting, grouping and filtering without ever touching the actual data.

Here’s a simple way to create a default view and apply sorting based on some property:

// _items is a collection of some type (e.g. Book)
ICollectionView view = CollectionViewSource.GetDefaultView(_items);
view.SortDescriptions.Add(new SortDescription(“BookName”, ListSortDirection.Ascending));

When a view is bound to an ItemsControl (via the ItemsSource property), the bound control uses the set sorting, grouping and/or filtering as appropriate. The problem with this in WPF 4, is that if a property (on which sorting is based, for example), changes value, and that change should move the object to a different location, that won’t happen. Here’s a simple example based on a DataGrid. A class named StockQuote is created; objects of that class are bound to a DataGrid, which allows sorting:

<DataGrid x:Name="_grid" AutoGenerateColumns="False" IsReadOnly="True" >
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name}" Header="Name"  />
<DataGridTextColumn Binding="{Binding Value}" Header="Value" />
</DataGrid.Columns>
</DataGrid
>
 
class StockItem : INotifyPropertyChanged {
   public event PropertyChangedEventHandler PropertyChanged = delegate { };

   public string Name { get; set; }

   double _value;

   public double Value {
      get { return _value; }
      set {
         _value = value;
         PropertyChanged(this, new PropertyChangedEventArgs("Value"));
      }
   }
}

In WPF 4.5, one can request the ICollectionViewLiveShaping interface and provide that as binding source to the control:
ICollectionViewLiveShaping view = (ICollectionViewLiveShaping)CollectionViewSource.GetDefaultView(_items);
view.IsLiveSorting = true;
_grid.ItemsSource = (System.Collections.IEnumerable)view;

 
To test things out, we’ll create a timer that changes a stock value randomly:
_timer.Interval = TimeSpan.FromSeconds(1);
_timer.Tick += (s, e) => {
foreach(var item in _items)
item.Value += rnd.NextDouble() * 10 - 5;
};
_timer.Start();

 
_timer is a DispatcherTimer, and rnd is a Random. Here’s how it looks at runtime:
image

It may not be obvious, but the lines move up & down, depending on the stock price (they are now sorted by the Value column). If we go back to the original ICollectionView interface, the sorting will not be maintained beyond the initial click.

The demo project is attached and can be opened by the Visual Studio 11 Preview (you can download it here).

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

2 comments

  1. louis vuitton alma bagApril 22, 2013 ב 12:18

    That is the suitable weblog for anybody who desires to seek out out about this topic. You understand so much its virtually onerous to argue with you (not that I actually would need匟aHa). You undoubtedly put a new spin on a topic thats been written about for years. Great stuff, simply nice!

    Reply