Posts Tagged ‘xna’

5
Jul
2012

XPF to be open sourced

by David Wynne

Way back in 2010 we announced the public beta of a new framework called XPF, a layout framework for XNA.  It enabled WPF/Silverlight style layouts to be created in XNA solving the pain point of doing 2D layouts in XNA.  It was built from the ground up in pure XNA, supported data binding, attached properties etc and came with a bunch of out of the box controls like Button, Border and the always popular Grid.

xna

What happened?

We were working on a project that had a huge amount of 3D and 2D content and as such was the test bed and, if you like, the thing driving the backlog of XPF.  We were also planning to productise XPF and sell licences so that others could use it in their products and we could make a few quid.

Two things happened.  The project we were working on fell by the wayside and Microsoft announced that they would allow you to combine Silverlight & XNA on the next version of Windows Phone 7 OS.  The impetus for XPF was lost and, as is often the case with start-ups, our attentions were focused elsewhere.

Where is XPF now?

The code for XPF is still sat in a private repo on github.com.  We really did do a ton of work on it, as you can see from the numerous blogs we wrote as we went.  There are literally hundreds of BDD specs covering every aspect and thousands of lines of code goodness.

We still get a lot of interest in XPF and pretty much decided months ago that there wasn’t the market to really productise it, so would instead turn it over to the open source community.  We didn’t really want to just flip the switch, make it public and slap an open source label on it however – we wanted some form of curation.  After all we’ve put a lot of our time and effort into the codebase.

What’s going to happen?

In February I started chatting to a Jaco & Jonathan in South Africa about what was happening with XPF and to cut a long story short, we’ve got to the point where they have agreed to shepard XPF into the open source arena – with some help from us of course.

Jaco, Jonathan & I have just had our first Skype call together to get the ball rolling and over the next couple of weeks they’re going to get the code base updated and ready to go public.

It would be great to see XPF brought back to life and to provide real benefit to those who’ve shown interest in it over the last couple of years.  We’re not totally sure how the project will pan out and obviously it’s early in our working relationship – but hopefully we’re moving in the right direction and together we can open up XPF to everyone!

23
Oct
2010

XPF: Data Binding 101 (Part 1) – What, Why, How?

by David Wynne

Data Binding is one of XPF’s features that we’re excited about – bringing data binding to the world of XNA helps to encourage building of loosely coupled applications and helps enable the separation of presentation from implementation logic.  We’ve previously discussed the inner workings of data binding in our insider post but for those whom data binding maybe an abstract concept, this series of posts is designed to introduce you to both the concepts and the implementation.  Let’s walk through what it is, why you should use it and what XPF offers.

What is Data Binding?

Data binding can essentially be thought of as an implementation of the Observer Pattern, where the UI is the observer and the domain model the subject.

“The observer pattern (a subset of the publish/subscribe pattern) is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.”
- Wikipedia

In reality XPF turns that concept on its head in that the UI elements maintain the list of subjects and hooks onto them to watch for updates, it also supports two-way conversations between subjects and observers but we’ll come onto that later.

Let’s step back slightly; XPF goes a bit further than the observer pattern so let’s change our language terms to something more fitting.  Instead of “subject” we’ll use source and in-lieu of “observer” let’s say target.  Let’s look at what that means in practical terms:

image

In this example we have a player class that exposes the player’s score via a property.  We also have a user interface which is going to display the player’s score as it updates.  In this example the score property on the player object is the source of our data and the text block in the UI is the target.  In a situation like this we would use data binding to establish a relationship between our player class and our UI once and then never worry about it again, knowing that if we alter the player’s score in our domain model the UI will automatically get updated via data binding.

Why use Data Binding?

Data binding is an enabler of other patterns and practices that ultimately make your life easier and your code easier to manage.

The quest to isolate domain logic from the user interface has spawned dozens of architectural patterns, MVC and MVVM being amongst the most popular at the moment.  Both concentrate on allowing your domain model to be focused on its job whilst being agnostic to any UI that maybe influenced by it.  This has some distinct advantages.

Generally speaking the logic you use to determine whether a player’s score should increase and the logic you use to display that change in score are very different beasts, as such when tackled together they don’t tend to produce particularly focused units of code.

Producing focused, isolated units of code makes your codebase easier to understand and eases unit testing.  If your player class doesn’t care about UI, then it doesn’t need to know anything about any graphics related dependencies, thus a dependency is dropped, unit testing is eased, and your code base is simpler and less brittle as a result.

Data binding encourages this separation by providing a bridge between the two disciplines.

Data Binding in XPF

As mentioned previously, XPF turns the Observer pattern on its head slightly in regards to which side of the equation maintains the list of observers (targets) that should be updated when the subject (source) changes.

In XPF the target maintains the list of sources with which it is bound.  The switch in responsibility here frees up the source (domain model) from being anything much other than a POCO.

The target is a UI element; all elements in XPF inherit from ReactiveObject and expose Reactive Properties which can be bound to.  Together ReactiveObject and ReactiveProperty provide the required mechanisms for data binding to work.

Three modes of binding are supported: one way, one way to source and two way.  The modes describe the direction in which data flows relative to the target.  One way is from the source to the target, one way to source is from the target to the source and two way moves data in both directions.imageWhilst all of the heavy lifting is taken care of by ReactiveObject and ReactiveProperty the source (domain model) side of the equation still has to agree to a couple of rules if it wants to take part.  The source needs to expose a known hook for the binding system to latch onto which it can use as a channel to push data in one or both directions.

In XPF this hook is provided by the new IObservable<T> and IObserver<T> interfaces introduced in .Net 4.0 (and on WP7) which align to the concept of moving data in either direction.  They are the mathematical dual of IEnumerable<T> and IEnumerator<T>, in that they push rather than pull their data.

“The IObserver<T> and IObservable<T> interfaces provide a generalized mechanism for push-based notification, also known as the observer design pattern. The IObservable<T> interface represents the class that sends notifications (the provider); the IObserver<T> interface represents the class that receives them (the observer).”
- MSDN

One way binding expects an IObservable<T> as its source which the binding system subscribes to.  One way to source expects an IObserver<T> to which the binding system can push updates.  Two way expects both.

How to use Data Binding

Continuing on the example application above, the score would be defined in the UI as a TextBlock and we would bind our player class to its text property.

Bindings are always setup against a ReactiveProperty on a ReactiveObject via the Bind() method.  In XPF all controls ultimately inherit from ReactiveObject and most expose a number of ReactiveProperty properties that can be bound to.

Each control exposes the Reactive Properties available for binding as static members, here are some of the Reactive Properties exposed by TextBlock, all of which can be bound to:

TextBlockReactiveProperties

Once we have an instance of a TextBlock we can call its Bind method and specify what property we want to bind to along with the mode and source we want to use.  It’s at this point we decide what binding mode we want to use by providing either an IObservable<T> (one way), IObserver<T> (one way to source) or both (two way):

TextBlockBind

The binding is now set and in the example above any changes to the source provided would update the TextBlock’s text property, meaning we don’t have to worry about updating the UI ourselves.

Don’t worry if all this talk of observables and observers is worrying you, we’ll cover the BindingFactory in a future post that can be used to create bindings around normal typed properties, but it’s good to get an understanding from the ground up.

Next Time…

In the next post in this series we’ll look at a domain object that exposes IObservable<T> and IObserver<T> properties and build a working sample that uses them to create both one way and two way bindings.

18
Oct
2010

XPF Video: Windows Phone 7 User Group Presentation

by David Wynne

At the last Windows Phone User Group, we took to the stage of Imperial College London and gave an introductory presentation on XPF.  For those that weren’t able to make it, we’re pleased to be able to present it to you now in 720p via the magic of IIS Smooth Streaming (we’ll also be making a downloadable version available shortly).

Topics include:

  • Why we need XPF
    • 2D in XNA Today
  • What is XPF
    • Controls
    • Extensibility
  • How to use XPF
    • Live demo: Embedding XPF inside a 3D application on WP7.

We’ve updated the XPF Samples package to include the full source code for the final 3D Basketball Game we built – you can download it here.

Massive thanks go to our good friend Mr Hornsby, the man behind the filming and editing of this presentation and of course Matt Lacey for organising the WPUG.  If you’d like to have a chat about video coverage of your event, drop Steve an email: steve@stephenhornsby.com

12
Oct
2010

XPF Control Tour: ItemsControl

by David Wynne

Updated 2010-10-20: Altered BindingFactory.CreateOneWay<SolidColorBrush> to CreateOneWay<Brush> – co/contravariance isn’t supported on WP7.  ItemTemplate now passes DataContext as an argument of the Func (Build 37+).

As XPF matures the number of controls available increases, but it’s largely down to the early adopter to seek them out and figure out how to use them.  Our thinking here is that most developers will have had some WPF/Silverlight experience so the usage pattern will be easy to work out.  That may have been a little presumptuous on our part, so in a series of short and sharp posts we’ll take a tour through some of the less obvious controls.

First up the ItemsControl, one of my favourites.  In XPF if you want to repeat a block of UI for n number of items, you invariably want an ItemsControl.  Think ListBox, ComboBox or maybe items in a menu.

Let’s look at a complete example and it’s output:

public class MyComponent : DrawableGameComponent
{
    private RootElement rootElement;

    public MyComponent(Game game)
        : base(game)
    {
    }

    public override void Draw(GameTime gameTime)
    {
        this.rootElement.Draw();
        base.Draw(gameTime);
    }

    public override void Update(GameTime gameTime)
    {
        this.rootElement.Update();
        base.Update(gameTime);
    }

    protected override void LoadContent()
    {
        var spriteBatchAdapter = new SpriteBatchAdapter(new SpriteBatch(this.GraphicsDevice));
        var primitivesService = new PrimitivesService(this.GraphicsDevice);
        var renderer = new Renderer(spriteBatchAdapter, primitivesService);

        this.rootElement = new RootElement(this.GraphicsDevice.Viewport.ToRect(), renderer);

        var colors = new List<SolidColorBrush>
            {
                new SolidColorBrush(Colors.Red), 
                new SolidColorBrush(Colors.Blue), 
                new SolidColorBrush(Colors.Yellow)
            };

        var itemsControl = new ItemsControl
            {
                ItemsSource = colors, 
                ItemTemplate = dataContext =>
                    new Border
                        {
                            Width = 50, 
                            Height = 50, 
                            Margin = new Thickness(10), 
                            Background = new SolidColorBrush(Colors.Gray)
                        }
            };

        this.rootElement.Content = itemsControl;
    }
}

image

That’s all standard XPF scaffolding code right up until we define a list of colors and define an ItemsControl.  Things to note:  ItemsSource is set to the list of colors (you can use anything that implements IEnumerable).  The ItemTemplate property is a Func<IElement> (all controls in XPF implement IElement) and is executed for each item specified in ItemsSource, hence we defined 3 colors in our list and we got 3 borders rendered.

The DataContext & Data Binding

At the moment each Border background is gray.  How do we get it to use the colors in our list?  Each item that the ItemsControl generates will have it’s DataContext property set to it’s associated item in the ItemsSource.  Using XFP’s data binding, we can bind to that DataContext property in our ItemTemplate and dynamically assign the background color of each Border:

var itemsControl = new ItemsControl
{
    ItemsSource = colors,
    ItemTemplate = dataContext =>
    {
        var border = new Border
        {
            Width = 50,
            Height = 50,
            Margin = new Thickness(10)
        };

        border.Bind(
            Border.BackgroundProperty,
            BindingFactory.CreateOneWay<Brush>());

        return border;
    }
};

image

Whilst the data context of each item is automatically set by XPF to support various binding scenarios, you’ll also note that the data context is passed as an argument of the ItemTemplate function.  This facilitates run-time decisions about the template that should be returned.

If you’re interested in all the Data Binding options, be sure to check out our Inside XPF: Data Binding post.

ItemsPanel

The way in which the ItemsControl lays out it’s children can be configured via it’s ItemsPanel property.  By default the ItemsControl will use a StackPanel (which itself defaults to an orientation of vertical).  But you can change the ItemsControl to use anything that inherits from Panel, meaning you can apply your own layout logic.  Custom panels is a subject in-upon itself which we’ll cover in a future post, but the process is almost identical to creating a custom panel in WPF/Silverlight, so generally speaking any WPF/Silverlight panel implementation you can find, will work in XPF.

For now, let’s change our ItemsPanel to a horizontal StackPanel:

var itemsControl = new ItemsControl
{
    ItemsPanel = new StackPanel { Orientation = Orientation.Horizontal },
    ItemsSource = colors,
    ItemTemplate = dataContext =>
    {
        var border = new Border
        {
            Width = 50,
            Height = 50,
            Margin = new Thickness(10)
        };

        border.Bind(
            Border.BackgroundProperty,
            BindingFactory.CreateOneWay<Brush>());

        return border;
    }
};

image

 

Observable Collections

In our example so far we’ve been binding our ItemsSource to a List<T> which means after creation our ItemsControl is pretty much not going to change.  If however you set the ItemsSource to a collection that implements INotifyCollectionChanged (such as the commonly used ObservableCollection<T>) the ItemsControl will automatically hook onto CollectionChanged event and dynamically, update it’s children.  All actions are supported meaning you can add, remove, replace or move items in the bound collection and the ItemsControl will automatically update it’s layout to reflect the changes.

Using the ItemsControl with an observable collection and data binding is another great example of XPF helping you separate your presentation and implementation concerns.

29
Sep
2010

Talking XNA with Shawn Hargreaves and Charles Cox

by David Wynne

To a lot of .Net developers XNA often appears to be a bit of an enigma – they might know roughly what it is, but they’re not really sure of its placement in the market or relevance to their work.  With Windows Phone 7 XNA is being edged into the limelight a little more and developers will no doubt be wondering whether it’s for them.

One of the great things about the work we’re doing with XPF, is in lowering that bar to entry.  XPF’s out-of-the-box controls will be familiar to you if you’ve come from a WPF/Silverlight background, but they still embrace the mechanics of XNA; leading you slowly into the wonderful world of 3D programming.

In a recent Channel 9 video Shawn Hargreaves and Charles Cox, from the XNA team, give a great interview on what XNA is, how it’s used, and the platforms it’s available on.  If you’re at all interested in XNA, but aren’t sure where to start – this is a great intro.

One of the subjects that comes up is the oft-asked “XNA and XAML” question and you might notice that at around the 32min mark Shawn happens to mention something that sounds a lot like XPF. ;)

So if you’re interested in dipping your toe in the XNA water, why not start by checking out our XPF Getting Started guide, download the sample code and let us know how you get on.

28
Sep
2010

Pocket Mechanic Prototype Demo

by Cain Ullah

Last week I wrote a blog XPF Demo: What’s in store describing some of XPF’s potential power to deliver 2D layouts in an XNA app, alongside 3D elements. In that post I also promised to post a video of us playing with the 3D model interface deployed onto a WP7 device.

So, as promised, you can view a video below with David taking you through some steps of manipulating a 3D prototype of a VW Beetle’s Distributor:

As described in the XPF Demo: What’s in store blog post, we will be building out a demo around this prototype to include XPF’s 2D layout functionality to illustrate the power of being able to combine 2D and 3D in such an elegant manner.

We’ll keep you posted with our progress as more nightly builds are delivered and will be following up with new videos and blog posts as we deliver more functionality.

26
Sep
2010

XPF: Introducing Adapters (and Clipping)

by David Wynne

Chocolate Tools by Janne Moren One of the things we’ve always been very careful to do with XPF is to make sure that it doesn’t really know anything about XNA.  Everything is interface driven and the link to XNA is only made at the “last minute” in the implementation of those interfaces.

This gives us the advantage of easing our BDD specs (everything can be mocked) but it also opens up another intriguing possibility – XPF doesn’t necessarily have to be used for XNA.

To reinforce this separation we’ve introduced the concept of adapters.  Those currently using XPF will know that we already have adapters, in the pattern sense of the word, for SpriteBatch, SpriteFont and Texture2D – but we’re extending the adapter concept to encompass everything required to use XPF on a platform, such as XNA.

There isn’t actually much new in the codebase as a result but we have moved some code about and created a new assembly.  Alongside RedBadger.Xpf.dll you’ll now find RedBadger.Xpf.Adapters.Xna.dll.  RedBadger.Xpf no longer references any XNA assemblies, but obviously the adapter dll does.  (This structure is mirrored in the WP7 assemblies).

As it stands there is only one XPF adapter – XNA, but in time there maybe more whether they’re written by us or by you!  We’ll be publishing the source code for the XNA adapter in the near future and giving  you a few more details on how you go about writing your own adapters, but in the mean time you’ll probably want to get the latest build, add a reference to the XNA adapter and fix up your code (should be fairly straight forward).

Other Changes (including Clipping)

Build 24 also brings with it clipping, which has meant a few changes to the way in which the SpriteBatchAdapter works.  We needed finer grain control over the SpriteBatch Begin and End calls (we use Scissor Testing to perform clipping which requires a change in RasterizerState) so you’re no longer responsible for calling SpriteBatch.Begin/End either-side of your call to RootElement.Draw.  To enforce this SpriteBatchAdapter no longer adapts SpriteBatch to ISpriteBatch via inheritance, but rather containment – so you physically can’t call Begin/End yourself.  This is consistent with the other adapters, so actually provides some nice usage symmetry too.

As a lot of the graphics related code has now been moved out of the main XPF assembly, we’ve re-organised our namespaces a bit.  Everything that was under Presentation has now moved up into the main Xpf namespace (Presentation is no longer).  We’ve also renamed XnaImage and ITexture2D to TextureImage and ITexture respectively.

As always, let us know how you’re getting on with XPF and thanks to all those who’ve provided feedback thus far, it’s been invaluable!

22
Sep
2010

XPF Demo: What’s in store

by Cain Ullah

We are now getting to the point where we have enough functionality in the XPF public beta to start building out a demo application to showcase its functionality. We are going to use the requirements of the demo application to drive functionality that has not yet been built (bear in mind that we still want your feedback as it will also have an impact on our priorities of delivery).

Whilst my two business partners, Stu and David (the techy ones) have been enjoying themselves developing XPF and blogging in anger as new nightly builds are released with cool new functionality – I’ve been concentrating on all the non-techy stuff.

So, to give you a heads up of what is in store for the demo that we want to deliver over the coming weeks, this post will go through a few scamps I have done to show some designs of the demo’s functionality.

XPF exists to allow you to build powerful 2D layouts alongside the already powerful 3D functionality that XNA offers.  To showcase XPF functionality the demo will be an XNA application on WP7 with a whole bunch of fluid and logical 2D layouts, combined with some 3D elements too. We have built the story around a pocket mechanic application on which you can view lots of the usual 2D stuff such as – large amounts of textual information, navigate pivot pages (specific to WP7), view thumbnail galleries, view full-screen images (and navigate between them), view menus and app bars etc… you will also be able to interact with 3D models.

So, let’s have a look at some scamps around the pocket mechanic app:

Pivots

Pivots         Pivots Nav

If you are familiar with WP7 you’ll already know that you can use long horizontal panoramic canvas’ that extend beyond the confines of the screen. It is as if you are using the phone as a magnifying glass to view content across the horizontal display (see to the right).

The horizontal canvas is made up of several pages, in this case pivot pages. A pivot is a control that allows you to navigate across large datasets or multiple pages. Flicking or panning horizontally on the page cycles the pivot, as does tapping a pivot header. In this case we have three pages: Text, Photos and 3D Parts.

The pivot control ships with the WP7 phone in Silverlight but remember this is an XNA app. To do this in XNA is somewhat of a challenge. So we will be using XPF to layout all of these pages, re-build the pivot control and create the animation and gestures to give a smooth experience when navigating between the pivot pages.

Textual Information

Textual Info The Text pivot page in the demo app will display a chapter of dummy text. This however could support full books of navigable text if necessary, using a Virtualizing Stack Panel.

An up or down swipe gesture will navigate through the text with the headings (chapter and section) remaining in place until you reach the next chapter or section. Such functionality is easy to implement with XPF’s Scroll Viewer.

Once animation is available in XPF, navigation will be in a smooth animated manner with built in physics controlling the speed of the text movement depending on the speed of the gesture.

To be able to build a 2D layout of navigable text, quickly, within an XNA app will be very powerful on both Windows and Windows Phone 7.

Thumbnail Galleries & Image Viewer

Images

You can view a thumbnail gallery of images separated out into their respective chapters and sections with each of the thumbnails having a title and description. Data driven layouts like this are easy to implement in XPF using the ItemsControl which can be configured with any panel – a Wrap Panel might be a good choice here. It is possible to navigate through all of the images in the application via vertical flicks on this pivot page.

Tapping  a thumbnail takes you to full screen mode of that particular image. Once in full screen mode you are able to zoom and move the view of a single image using pinch and pan gestures. To navigate to the next picture without exiting full screen mode you flick horizontally and if you want to exit full screen mode you can either tap the back button on the phone’s hardware (to go back to the thumbnail view) or tap the home button on the app bar to return to start page of the application.

App Bar and Menu Items

With Silverlight applications on the WP7 you get an application bar which allows you to display up to four buttons used to invoke the most common application tasks. This does not ship with XNA applications. So, by using XPF we have created the ability to generate your own app bars to interact with your XNA application. In the demo we have a common app bar that will be consistent across the application as well as a menu item app bar that we will use to interact with the 3D content.

Lets have a quick look at the menu item app bar that we’ll use to interact with the 3D models…

When we are in 3D mode we want to provide a flexible way to manipulate the view of the model you are looking at. This will include picking a specific component within a model by interacting directly with the 3D model.

However, we also want to provide some contextual 2D textual information to show what you are looking at as well as some efficient ways to navigate to specific components on the model without having to interact with the 3D model itself. To do this, we are going to build a menu item.

Menu Item App Bar

As you can see in the scamp (above), when first entering into 3D mode for a specific model, you will be presented with the menu item that sits on top of the app bar. By default no component will be selected. Selecting the text (in this case ‘None Selected’) will present you with a list of selectable components or by using the left and right arrows you can cycle through the components one at a time. If you tap the text ‘None Selected’, the menu item will raise upward, revealing a list of components that you can select within the model. You can select any of the components from within the list and the menu item will collapse back down to the app bar (hiding the list) and you will be ‘flown’ to the optimum viewing angle of the specific component of the 3D model. Cycling through the components by using the left and right arrows “Flies to” and “Picks” components in the same way.

3D Content

Whilst the 3D content does not demonstrate XPF functionality directly, it does demonstrate the sort of situation that has brought about its creation – you would not be able to build this sort of 3D interactive functionality in Silverlight.  XPF allows you to combine both 3D and 2D, linking the two worlds using powerful data binding to create elegant implementations.

Summary

So to summarise, hopefully this blog will give you an idea of some of the things that you are able to build by using XPF within your XNA applications. Our complete set of scamps around this demo app are much more in-depth with lots more ideas for future functionality. However, what we actually build for a demo app will be closer to what I have talked about in this post.

We’ll post a video shortly of us playing with the 3D model interface deployed on a WP7 device.

We’ll continue to build out XPF with new cool features in the mean time. More blogs to follow and of course, more nightly builds.

21
Sep
2010

XPF: Star Grid Length and Windows Phone 7 Orientation

by David Wynne

We recently added support to XPF’s Grid for star grid length.  Star grid lengths describe a grid layout using proportional values, allowing you to split up available space using percentages.  This can be extremely powerful, especially in situations when your host window changes size – think going in and out of full screen on Windows or changes in orientation on Windows Phone 7.

In our original Getting Started post, we had to use explicit row height and column widths creating a slightly inflexible structure.  Let’s rewrite the code using star grid lengths, but this time on Windows Phone 7.

Star Grid Length

We want to create a Grid with the following characteristics:

Grid

Because star is now the default grid length unit, to get the above layout we only have to provide explicit values on our top and bottom rows; making them a fixed height of 50 pixels each.  The middle row can default to what is effetely a value of 1 star, which will use 100% of the remaining space.  The 2 columns both have 1 star too and so will share the available horizontal space equally between them; 50% each.

var grid = new Grid
{
    Background = new SolidColorBrush(Colors.White), 
    RowDefinitions =
        {
            new RowDefinition { Height = new GridLength(50) }, 
            new RowDefinition(), 
            new RowDefinition { Height = new GridLength(50) }
        }, 
    ColumnDefinitions =
        {
            new ColumnDefinition(),
            new ColumnDefinition()
        }
};

The rest of the code from the Getting Started sample is exactly the same.  The result is a layout that stretches itself to the available space:

image

Windows Phone 7 Orientation

Now that we have a flexible layout, we can change the RootElement’s viewport whenever we want and XPF will re-evaluate our layout for us.  Let’s continue our example, by looking at how we might handle changes in orientation on WP7.  First let’s tell XNA that we can support all forms of orientation:

new GraphicsDeviceManager(this)
{
    SupportedOrientations =
        DisplayOrientation.Portrait |
        DisplayOrientation.LandscapeLeft |
        DisplayOrientation.LandscapeRight
};

Next we need to hook-up to the OrientationChanged event, changing XPF’s RootElement.Viewport in the handler.  You could do this using standard event handlers, but I’m going to use Reactive Extensions (Rx) so it will handle unhooking the event later if RootElement is disposed:

Observable.FromEvent<EventArgs>(
        handler => this.Game.Window.OrientationChanged += handler,
        handler => this.Game.Window.OrientationChanged -= handler)
    .Subscribe(_ => this.rootElement.Viewport = this.Game.GraphicsDevice.Viewport.ToRect());

That’s it we’re done.  Let’s fire it up and rotate our phone through 270 degrees and see the result:

A few lines of code and our entire layout becomes fluid and reflows without any manual intervention.  Building fluid layouts allows us to use the exact same code to target multiple resolutions and frees us from having to think too hard about how that impacts our implementation.

Star grid length and resizable RootElement are both available in the latest Nightly Build.

13
Sep
2010

Inside XPF: Data Binding

by Stuart Harris

Updated 2010-09-20: Reflects the removal of the generic type parameter TOwner from ReactiveProperty (starting Build 20).

Neuroanatomical Connectivity Macaque by Arenamontanus In the previous post in this series, we discussed XPF’s Reactive Properties – the counterpart to Silverlight’s Dependency Properties.  Reactive Properties allow you to data bind to any source that implements the new .Net 4.0 IObservable<T> (for one-way binding) and/or any source that implements IObserver<T> (for one-way-to-source binding).  Two-way binding is simply a combination of the two.

The Reactive Object

In Silverlight, all UI Elements are derived from DependencyObject which the MSDN documentation says “Represents an object that participates in the dependency property system”.  In XPF all UI Elements are derived from ReactiveObject which represents an object that participates in the reactive property system.  ReactiveObject not only stores the current values of all the element’s reactive properties, but also allows you to bind to them in either (or both) directions.

The Bind method has overloads that allow you to bind a ReactiveProperty one-way to an IObservable, one-way-to-source to an IObserver or two-way to both.

The Binding Factory

So what do you do if the object you want to bind to doesn’t expose an IObservable/IObserver?  This is where the BindingFactory comes in.  The BindingFactory will create IObservables and IObservers around properties on either the data context or a specified source.

Binding to reactive properties, or properties on POCOs and objects that implement INotifyPropertyChanged is fully supported.  This enables element-to-element binding in addition to the use of familiar binding patterns often used in WPF/Silverlight such as Model View ViewModel (MVVM).

The observable/observer that the BindingFactory creates for you is internally wrapped in a Binding object which allows for either immediate or deferred resolution of the binding.  Immediate resolution is used when a reference to the source is provided, but if you are binding to an element’s data context then the binding resolution is deferred until the start of the Measure layout phase.  Deferred bindings are great because they allow the data context to be set or changed after the element binding has been declared.  This is essential for controls that use templates such as the ItemsControl.  The Binding’s resolution is handled seamlessly.

All data binding scenarios are supported.  The following table shows the various combinations of source objects/properties in each mode.  Note that binding to POCO properties works in both directions, but without INotifyPropertyChanged (INPC), one-way binding effectively becomes “one-time”.

Data Context
/Source Object
Reactive
Property
INPC
Property
CLR
Property
One-way Supported Supported Supported Supported
(one-time)
One-way-to-source Not applicable Supported Supported Supported
Two-way Not applicable Supported Supported Supported
(one-time and one-way-to-source)

Show me some code

Here are the overloads to ReactiveObject’s Bind method:

Bind

You’ll notice that because it’s a generic method, the parameters are strongly typed to match the target ReactiveProperty specified.  The scenario in the screenshot above shows binding to a source reactive property on the element’s data context.  The specification for this scenario looks like this:

[Subject(typeof(ReactiveObject), "One Way")]
public class when_there_is_a_one_way_binding_to_a_property_on_the_data_context
{
    private const double ExpectedWidth = 10d;

    private static SourceObject source;

    private static ContentControl target;

    private Establish context = () =>
        {
            target = new ContentControl();

            IObservable<double> fromSource =
                BindingFactory.CreateOneWay<SourceObject, double>(SourceObject.WidthProperty);
            target.Bind(UIElement.WidthProperty, fromSource);

            source = new SourceObject();
            target.DataContext = source;
            target.Measure(Size.Empty);
        };

    private Because of = () => source.Width = ExpectedWidth;

    private It should_update_the_target = () => target.Width.ShouldEqual(ExpectedWidth);
}

Because we’re binding to the control’s data context the binding resolution is deferred until the target is measured.

Using the Binding Factory

Here are some examples of how to create Bindings using the Binding Factory.  Those that involve the data context are all deferred and those where the source is specified are all immediate.  An IDualChannel simply encapsulates both an IObservable and an IObserver so that data can flow in both directions (to and from the source).

Notice that you only need to specify type parameters when there is not enough information in the method’s parameters for the compiler to infer the types involved:

To the Data Context

IObservable<double> fromSource =
    BindingFactory.CreateOneWay<double>();

IObserver<double> toSource =
    BindingFactory.CreateOneWayToSource<double>();

To a Reactive Property on the Data Context

IObservable<double> fromSource =
    BindingFactory.CreateOneWay<SourceObject, double>(SourceObject.WidthProperty);

IObserver<double> toSource =
    BindingFactory.CreateOneWayToSource<SourceObject, double>(SourceObject.WidthProperty);

IDualChannel<double> fromAndToSource =
    BindingFactory.CreateTwoWay<SourceObject, double>(SourceObject.WidthProperty);

To a Reactive Property on a specified Source

IObservable<double> fromSource =
    BindingFactory.CreateOneWay(source, SourceObject.WidthProperty);

IObserver<double> toSource =
    BindingFactory.CreateOneWayToSource(source, SourceObject.WidthProperty);

IDualChannel<double> fromAndToSource =
    BindingFactory.CreateTwoWay(source, SourceObject.WidthProperty);

To an INotifyPropertyChanged or CLR Property on the Data Context

IObservable<double> fromSource =
    BindingFactory.CreateOneWay<SourceObject, double>(o => o.Width);

IObserver<double> toSource =
    BindingFactory.CreateOneWayToSource<SourceObject, double>(o => o.Width);

IDualChannel<double> fromAndToSource =
    BindingFactory.CreateTwoWay<SourceObject, double>(o => o.Width);

To an INotifyPropertyChanged or CLR Property on a specified Source

IObservable<double> fromSource =
    BindingFactory.CreateOneWay(source, o => o.Width);

IObserver<double> toSource =
    BindingFactory.CreateOneWayToSource(source, o => o.Width);

IDualChannel<double> fromAndToSource =
    BindingFactory.CreateTwoWay(source, o => o.Width);

Clearing a Binding

To clear a binding simply call the ClearBinding() method on the relevant control, specifying the reactive property whose binding you want to clear:

element.ClearBinding(Border.BorderBrushProperty);

Because an instance of ReactiveObject can only have one binding per property, calling the Bind() method replaces any existing binding.  Internally it calls ClearBinding() before attaching the new binding.

When a binding is cleared, its subscription to the source is automatically disposed.  This releases any attached event handlers (created automatically in order to listen to PropertyChanged events) which helps prevent memory leaks.  This is a great feature of Microsoft’s Reactive Extensions (Rx) that frees the developer from worrying about having to un-hook event handlers when an observer is no longer interested in the event.

Even though there can only be one binding at a time to an element’s property, you can still merge multiple observables together using any of the Rx combinators (Merge, Zip, CombineLatest etc) if you want your reactive property to listen to more than one source.

Summary

We hope that the binding system in XPF is simple to understand and easy to use.  Whilst the underlying property system in XPF is push based (rather than pull), we’ve strived to keep the development experience familiar to Silverlight and WPF developers.

The tight integration with Reactive Extensions makes it extremely flexible and powerful.  The statically typed nature of the binding and property system makes it intuitive, discoverable and refactoring friendly.  The absence of any magic strings means that there should be no run-time binding exceptions when a deferred binding cannot be resolved.  Binding to nested properties is currently not supported, but we plan to introduce this using the same strongly typed lambda expression syntax shown above.

Please download the latest build, play about with it and feedback to us!

Inside XPF Series: