Application Model and Data Binding on Windows Phone 7

Model-View-ViewModel (MVVM) is a very useful pattern for organizing scalable and constantly evolving phone applications.  In MVVM, Each view is backed by a view-model and a model.  Models are loaded from storage or the network often as pages are displayed to the user. 

Joe Healy co-author of the Teach Yourself Windows Phone 7 Application Development in 24 Hours comments that many phone developers are not using nor are familiar with MVVM and that this pattern is applicable for any app that is sharing global app data across multiple pages.

Sams Teach Yourself Windows Phone 7 Application Development in 24 Hours (Sams Teach Yourself — Hours)

In Phone applications it is desirable for the performance of page navigation to be as fast as possible.  Users do not have the tolerance for waiting several seconds between pages as they do on web applications.  To remedy this, phone applications often place their models at the application scope so that they may be accessed by all the pages.  This does not mean that all the data is loaded at application start though.  The application model acts as a cache for that data that has been loaded.

One implementation might be to define an ApplicationModel class and define it as a resource in the app.xaml file.  Then Any data binding can be trivially done within XAML.  An issue occurs this that approach. 

<Application.Resources>
<app:ApplicationModel x:Key="ApplicationModelK" />
</Application.Resources>
 
<TextBlock Text="{Binding Source={StaticResource ApplicationModelK}, Path=SomeData}"/>
 
 

Both One-Way and Two-Way data binding rely on INotifyPropertyChanged event on the binding.  The Binding also has a reference to the bound UI control which has a reference to the page.  When the user navigates back (exiting the page), the page stack no longer holds a reference to the page and the page would normally get garbage collected. 

 

But since a reference still exists from App->ApplicationModel->SomeData->Binding->UI Control->Page then the page never gets garbage collected.  This page reference leak results in all the resources of the page being held in memory.  Further, when the user returns to the page, a second page instance is created and all the resources reallocated again.  Also, when the ApplicationModel data changes both the old and new instances of the page are notified.

One solution to this is to not bind directly to the global ApplicationModel but instead set the page.DataContext to the ApplicationModel.SomeData when inside of OnNavigatedTo and to set DataContext to null on OnNavigatingFrom.  Then in your binding you bind only to the partial object path rather than the global reference. 

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
    DataContext = Application.Current.Resources["ApplicationModelK"];
    base.OnNavigatedTo(e);
}
protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
    DataContext = null;
    base.OnNavigatedFrom(e);
}
 
<TextBlock Text="{Binding SomeData}"/>

 

With this pattern the binding to global data will be removed when exiting the page and the references back to the page will be release allowing the page to be garbage collected.

Posted in Uncategorized | Leave a comment

Performance UI Pattern: Asynchronous Property

Motivation: XAML development thrives on declarative data binding. The means that at author-time a unique path to each piece of data to be displayed is known. At runtime when the data binding is interpreted a property is called to retrieve the data. This retrieval may take time causing a delay for each visual element in a displayed user interface.

Anti-pattern 1: Data is loaded then it is presented to the UI. In this anti-pattern the developer often loads more content than needed for the currently visible user interface. This causes more delay before the UI is fully presented.

Anti-pattern 2: On-demand loading of properties (Lazy Initialization Pattern) as they are presented in UI. In this anti-pattern the data the retrieved when it is first requested. This property get blocks until the property data is ready.

Asynchronous Property Pattern: This pattern allows for on-demand request of the property which instantly returns an object which represents the property which will be populated once the load is completed. The asynchronous property provides properties for value and status. Because the asynchronous property is retrieved installs, data binding to both the value and the status.

AsyncProperty demonstration Windows Phone 7 application download here:

http://cid-ac1291870308f748.skydrive.live.com/embedicon.aspx/Public/AsyncPropertyDemo.zip

Posted in Uncategorized | Leave a comment

Updating ApplicationBarIconButton dynamically

Since the ApplicationBar is not a DependencyObject and not part of the visual tree, FindElement cannot locate Items in the ApplicationBar with x:Name set.  The members will be null.

 

Due to this, it may be best to initialize the ApplicationBar using code behind and hold references to items which need to be dynamically changed.

 

Notice in the code below that SaveEdit reference is held and SaveEdit.IsEnabled is updated with each keypress into the TextBox.

 

#region AppBar

private ApplicationBarIconButton SaveEdit;

private void InitAppBar()

{

ApplicationBar appBar = new ApplicationBar();

appBar = new ApplicationBar();

 

SaveEdit = new ApplicationBarIconButton(new Uri(“images/appbar.check.rest.png”, UriKind.Relative));

SaveEdit.Click += new EventHandler(OnClick_Check);

//SaveEdit.Text = Strings.Save_button;

appBar.Buttons.Add(SaveEdit);

 

ApplicationBarIconButton CancelEdit = new ApplicationBarIconButton(new Uri(“images/appbar.close.rest.png”, UriKind.Relative));

CancelEdit.Click += new EventHandler(OnClick_Cancel);

//CancelEdit.Text = Strings.Cancel_button;

appBar.Buttons.Add(CancelEdit);

 

ApplicationBar = appBar;

}

#endregion AppBar

       

 

 

void itemName_KeyDown(object sender, KeyEventArgs e)

{

bool isNameValid = itemName.Text.Length != 0;

           

if ((e.Key == Key.Enter) && isNameValid)

{

SaveAndExit();

}

           

SaveEdit.IsEnabled = isNameValid;

}

 

Posted in development, wp7 | Leave a comment

Ship it! One Giant Rubik’s Cube

 

In February I was on a ski trip with some friends and Barry began talking about building a giant Rubik’s Cube.  This week, just 6 months later the Groovik’s Cube was assembled at Burningman and looks spectacular.  It was event mentioned in Gizmodo.

The project involved 9 project leads, over 50 volunteers, and many hours of volunteer work.  Bringing together skills from electronics, software, fabric, adhesives, and metal. 

Early in the project, Rhonda created a simulator for the project so we could see how our control scheme would work.  This early feedback allowed us to discuss and change our user interface scheme.

I was a lead on the electronics side focusing on production of surface mount circuits to regulate current to the hundreds of super bright LEDs.  I did not attend Burningman to witness the cube in person ad our timeline did not allow us to do a fully assembly before.  So, I have yet to see the whole cube operating.  I bet it is quite a site!

Posted in Uncategorized | Leave a comment

Live Geometry

Here is a great example of the richness that can be created with simple tools available with Silverlight.

 Live Geometry

Posted in Uncategorized | Leave a comment

Serializer .NET Robot Controller

 

This looks like a decent board with support to multiple wireless computer interfaces.

Serializer .NET Robot Controller

Posted in Hobbies | Leave a comment

New Cider Adorner Placement API’s

In my last post I discussed the 3 adorner spaces in the new Cider adorner placement API’s.  In this post I will discuss these API’s  in a little more detail.  Note at the time of this writing, the spcific class and property names have not been finalized.  jnak will be asking for your input in his blog See Win App.  We’d like to know your thoughts on the names since we traditionally work with a single coordinate system in user interface developement, supporting 3 coordinate systems can be confusing. 

The driving goal of the last set of changes has been to support a concept of layout space.  I’ve also taken this opportunity to simplify the setting of adorner placement and open the adorner panel arrange so it can be extended by external developers.  I’ve tried to simplify this so developer can create designer features without dealing with the math am atricies associated with layout transforms, render transforms, right-to-left(RTL) language transforms, and zomming content in the designer view.  With you help we can take this next step at nameing and organizing these classes and properties to make them easiest to use.

Please visit jnak’s blog and give us your feedack See Win App.

In this example, the parent grid has a render transform X-skew of 5 degrees. Though this scenario is useful for demonstrating the affects of the different spaces.

Notice the selection frame and grab handles in the grid are unaffected by the skew of the grid render transform. These adorners are adorning the position the grid is within its parent. Since the grid’s parent is unaffected by the grid’s render transform, the grid layout space is also unaffected by this transform.

Notice that the button’s selection frame and grab handles ARE affected by the render transform of the grid. Since the layout position of the button is in the coordinate system of the rendered grid, the square layout slot of the button has been skewed by the transform.

 

Scenario: Top Grid Rail

Here is the code for placement of the top grid rail. This adorner is in the render space of the grid, is stretched from the left hand to the right hand side of the grid, is positioned outside the top grid edge, and has a height determined by the adorner XAML style. The height does not scale when the designer zooms in.

// start with empty placement
ContributionGroup placement = new ContributionGroup();
placement.Add(new SizeRelativeToAdornerDesiredHeight(this, 1.0, 0));
placement.Add(new SizeRelativeToContentRenderWidth(null, 1.0, 0));
placement.Add(new PositionRelativeToAdornerHeight(this, 0, -offsetY));
AdornerPanel.SetPlacement(this, placement);
AdornerPanel.SetHorizontalStretch(this, AdornerStretch.Stretch);
AdornerPanel.SetVerticalStretch(this, AdornerStretch.None);

Scenario: TopRightGrabHandle

This adorner is sized to the according to the XAML style. This adorner is positioned in the layout space of the adorned element and positions at the right hand side of the adorned element. The position is adjusted 3 pixels further right and upward by the height of the adorner plus 3 pixels in order to locate it outside of the top right edge fo the adorned element’s layout position.

ContributionGroup placement = new ContributionGroup();
placement.Add(new SizeRelativeToAdornerDesiredWidth(this, 1.0, 0));
placement.Add(new SizeRelativeToAdornerDesiredHeight(this, 1.0, 0));
placement.Add(new PositionAtContentLayoutSlot(null));
placement.Add(new PositionRelativeToContentLayoutWidth(null, 1.0, 0));
placement.Add(new PositionRelativeToAdornerWidth(this, 0, -3.0));
placement.Add(new PositionRelativeToAdornerHeight(this, -1.0, 3.0));
AdornerPanel.SetPlacement(this, placement);

Proposed Placement Classes

Contribution Group

This is a collection of class instances that declare adjustments to the adorner size and position.  This is a temporary name, other names we have tossed around are ArrangementGroup and PlacementGroup.

Please offer you suggestion at jnak’s blog.

Adorner Space

The adorner space properties allow you to adjust the size off the adorner based on the desired size determined by the style size of the adorner.  Adorner position can be adjusted relative to the final computed size fo the adorner.  Size and position can also be adjusted in pixels.  Adorner space does nto scale when the designer zooms in/out.

SizeRelativeToAdornerDesiredHeight(relativeTo, factor, offset)
SizeRelativeToAdornerDesiredWidth(relativeTo, factor, offset)
PositionRelativeToAdornerHeight(relativeTo, factor, offset)
PositionRelativeToAdornerWidth(relativeTo, factor, offset)

Render Space

The render space properties allow you to adjust the size or position of the adorner relative to the adorned element and by an offset measured in pixels in thatcoordinate system.  Render space size and positions adjustments are affected by and transform that affects the render size and shape of the adorned element.

SizeRelativeToContentRenderHeight(relativeTo, factor, offset)
SizeRelativeToContentRenderWidth(relativeTo, factor, offset)
PositionRelativeToContentRenderHeight(relativeTo, factor, offset)
PositionRelativeToContentRenderWidth(relativeTo, factor, offset)

LayoutSpace

The layout space properties allow you to adjust the size or position of the adorner relative to the layout slot fo the adorned element and an offset measured in pixels of that coordinate system.  Layout space size and positions are afected by transforms that affect the render space of the adorned element parent.

SizeRelativeToContentLayoutHeight(relativeTo, factor, offset)
SizeRelativeToContentLayoutWidth(relativeTo, factor, offset)
PositionAtContentLayoutSlot(relativeTo )
PositionRelativeToContentLayoutHeight(relativeTo, factor, offset)
PositionRelativeToContentLayoutWidth(relativeTo, factor, offset)

Posted in Uncategorized | Leave a comment