SharpGIS

#GIS from a .NET developer's perspective

RefreshBox for Windows Phone 7

I always liked the simplicity in iPhone for refreshing a list of various feeds, for instance email, tweet, RSS etc. Basically when you get to the top of the list, you simply keep pulling and the app will check for the latest items:

image

I wanted something similar in my WinPhone application, and ventured out to make this. You could probably go and argue now that Windows Phone 7 shouldn’t be copying ideas from other phones but be its own, which is a somewhat fair argument, but when something just works, it just works. So yes this post is about totally ripping of an iPhone idea. I’ll admit that Smile

If you don’t care how this was done, just jump to the bottom to see the result in action, and/or download the bits.

Anyway, luckily creating a control like this wasn’t too hard. It starts with inheriting from the ListBox control which has all the list features needed. It also supports pulling beyond the contents of the list and when you let go, it “pops back” to the top item. So all I need to do, is :
1. Find a way to place an item in this “outside area”.
2. Detect that the user is pulling the list out in this area.

Placing the element in the outer area proved to be really simple. The ListBox template is basically just a ScrollViewer with an ItemsPresenter inside it. So all we need to do is place a grid with the contents on top of the ItemsPresenter with a negative vertical margin:

<ControlTemplate TargetType="local:RefreshBox"> 
    <ScrollViewer x:Name="ScrollViewer" ...> 
        <Grid> 
            <Grid Margin="0,-90,0,30" Height="60" VerticalAlignment="Top" x:Name="ReleaseElement"> 
                <!-- content goes here --> 
            </Grid> 
        </Grid> 
        <ItemsPresenter/> 
    </ScrollViewer> 
</ControlTemplate>

Sprinkle a little visual states in that content, and we would be able to change the message when we detect the user has been pulling beyond the threshold.

The first thing we do is get a reference to the ScrollViewer and the ReleaseElement during OnApplyTemplate(), and listen to MouseMove (the event that causes the scrolling) and ManipulationCompleted (triggered when the user lets go of the screen).

public override void OnApplyTemplate() 
{ 
    base.OnApplyTemplate(); 
    ElementScrollViewer = GetTemplateChild("ScrollViewer") as ScrollViewer; 
    if (ElementScrollViewer != null) 
    {            
        ElementScrollViewer.MouseMove += viewer_MouseMove; 
        ElementScrollViewer.ManipulationCompleted += viewer_ManipulationCompleted; 
    } 
    ElementRelease = GetTemplateChild("ReleaseElement") as UIElement;        
    ChangeVisualState(false); 
}

In MouseMove we can then check the VerticalOffset of the ScrollViewer. You would think this offset is negative, but it gets clamped at 0, so we can’t use that. Instead by calculating where the ReleaseElement is physically located gives us an idea of how far we pulled:

private void viewer_MouseMove(object sender, MouseEventArgs e) 
{ 
    if (VerticalOffset == 0) 
    { 
        var p = this.TransformToVisual(ElementRelease).Transform(new Point()); 
        if (p.Y < -VerticalPullToRefreshDistance) //Passed thresdhold : In pulling state area 
        {             
            //TODO: Update layout//visual states 
        } 
        else //Is not pulling 
        { 
            //TODO: Update layout/visual states 
        } 
    } 
}

Similarly, when you let go of the screen we make the same check and raise an event if necessary:

private void viewer_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e) 
{ 
    var p = this.TransformToVisual(ElementRelease).Transform(new Point()); 
    if (p.Y < -VerticalPullToRefreshDistance) 
    { 
        //TODO: Raise Polled to refresh event 
    } 
}

So here’s that this looks like….

Scrolled to the top of the list:

image

Pulling slightly down on the listbox beyond the top item:

image

Pulling all the way down: Message tells you to let go to refresh:

image

And here’s what that look like in action:

You can download the code and binary for a fully skinnable control/reusable below here:

Source : SharpGIS.Controls.RefreshBox_source.zip (32.31 kb)

Binary : SharpGIS.Controls.RefreshBox_binary.zip (6.48 kb)

UPDATE: If you are using v7.1 (Mango), the above approach will only work if you set ScrollViewer.ManipulationMode ="Control" on the RefreshBox. See herefor details.

Using the accelerometer to control planar transforms on Windows Phone 7

Lately I’ve been looking into some Augmented Reality uses on Windows Phone 7, and one of the first things you need to do for this, is to use the sensors to control what’s displayed on the phone screen.

So the first step for me was to better understand how the accelerometer interacted with the phone’s orientation. I wanted to create a simple “3D Plane” that was always looked like it was “level”. This could be accomplished with a Rectangle and a PlaneTransform. The only question is: How do I transform the accelerometer values to the RotationX/Y/Z rotation angles on the PlaneTransform?

To make matters worse, depending on whether your phone is currently in Portrait, LandscapeLeft or LandscapeRight mode, the screen coordinate system, and thus the transforms changes, even though the accelerometer report the values independent of screen orientation. So to get a property transform, we also need to know what way the screen coordinate system is oriented relative to the accelerometer coordinate system.

With a little trigonometry it wasn’t too hard to figure out, so here’s the code to perform this little app.

First the border we used as the “level” plane:

<Border x:Name="plane" BorderBrush="Green" BorderThickness="2"
        Width="350" Height="350" >
    <Border.Projection>
        <PlaneProjection x:Name="proj"  />
    </Border.Projection>
</Border>

Next, create an accelerometer instance, and call “Update” every time we get a reading:

var meter = new Accelerometer();
meter.ReadingChanged += meter_ReadingChanged;
...
private void meter_ReadingChanged(object sender, AccelerometerReadingEventArgs e)
{
    Dispatcher.BeginInvoke(() =>
    {
        UpdateRotation(e.X,e.Y.e.Z);
    });
}

Lastly, update the PlaneProjection parameters, based on the rotation (this is where the “real meat” is):

private void UpdateRotation(double x, double y, double z)
{
    var offset = 0d;
    //Adjust for screen orientation when in landscape mode
    //PortraitUp mode doesn't need an offset
    if (Orientation == PageOrientation.LandscapeLeft) offset = .5;
    else if (Orientation == PageOrientation.LandscapeRight) offset = 1.5;                

    var rx = (Math.Acos(z) / Math.PI + 1) * 180;
    var rz = (offset - Math.Atan2(x, y) / Math.PI + 1) * 180;
    if(!double.IsNaN(rz)) proj.RotationZ = rz;
    if(!double.IsNaN(rx)) proj.RotationX = rx;
}

And lastly, here’s what this looks like (note how the screen orientation flips when the phone is rotated, but the plane stays in the same place):

Note that this sample doesn’t deal with calibration. I suggest you look at this blogpost on how to do that. It also includes a lot of information on the accelerometer in general. That blog also discusses filtering the noisy data which is important to give a smooth looking result. The sample code you can download below, includes a simple low-pass filter to make it feel a lot smoother.

Download source code

Lastly here’s an example/preview of a little Augmented Reality app I’ve been working on that is using this approach to overlay the camera feed with azimuth values:

Submitted my first WinPhone 7 Application

imageI’ve just submitted my first application to the Windows Phone Marketplace. It’s a very simple app that creates a “Guide Post” with signs on a pole showing distances and direction to any point in the world. You have probably seen these at various sites all over the world, or in the TV Show “M*A*S*H”.

It’s all built in Silverlight, and uses PlaneProjection to give give the signs a 3D effect. You use your finger to slider over the screen to rotate it.

In addition to that there’s a Map where you can view your current location and the great circle line (ie. shortest path) between you and the points of interest. This is of course using the ESRI ArcGIS API for Windows Phone that we just released.

Below is a few screenshots and a video clip of the app in action.

screen_12-1-2010_8.51.30.996screen_12-1-2010_8.50.48.336
screenshot_12-2-2010_12.26.46.864screenshot_12-2-2010_12.27.59.830

GuidePost Screen Capture

It was a great fun little app to build and only took a few evenings to get done. You can download the app to your phone from this link: http://bit.ly/WP7GP

Displaying HTML in Silverlight

In my second post in the series of ripping off other peoples work :-) here’s an updated version of David Anson’s HtmlTextBlock control back from 2007.

This was originally written based on the TextBlock control, but since the TextBlock control was sealed and couldn’t be inherited from, it required a lot of copying properties around. Textblocks also only supports text, so the HyperLink method was not really a hyperlink, and there was no image support, but from what we had available back them, it was a really good solution considering the simplicity (I like simple small implementations).

Since then Silverlight 4 has arrived, and we now have the RichTextBlock control. This supports hyperlinks, images etc, and it is not sealed, so we can pretty easily get around the limitations that the original implementation had. Most of the logic for generating the HTML is the same, but now with proper support for images and real hyperlinks. Again all the credit goes to the original author. I just did some tweaks.

You can download the source with a sample app here: HtmlTextBlock.zip (34.15 kb)

UPDATE: Rewrote the parser approach quite a lot. Now it also supports tables (!) as well as setting fontsize using the H1..H4 tags. With the new parser approach it should be easier to add support for other more complex tags as well.

You can download the source with a sample app here: HtmlTextBlock_v2.zip (34.15 kb)

REALLY small unzip utility for Silverlight – Part 2

I earlier blogged about a very small unzip utility for Silverlight.

However there was one problem with the method: It relied on some Silverlight framework libraries that didn’t support all zip file formats (a known bug I’m told). Some file zippers places the file size after the zip data chunk, and Silverlight does not like that. So I added a little bit to the utility to detect this case and if so, will re-arrange the bytes in the zipfile so Silverlight will read it.

So I present to you: The really small unzip utility v.2.0. It’s slightly larger than before, but still under 200 lines of code (plus comments).

It works the same way as before, so read the original blogpost to see how to use it.

Although I only tested this on Silverlight 4 and WinPhone 7, it should work with earlier Silverlight releases as well.

Download here: SharpGIS.UnZipper_v2.zip (2.53 kb)

Also available at NuGet

Code Syntax Highlighting in Silverlight

A little while back, Jeff Wilcox wrote an awesome syntax highlighter (blog post here). It enables you to display code in Silverlight with similar syntax highlighting that we know and love from Visual Studio. This is really useful if you want to display some code samples inside your Silverlight application.

However it had one major feature missing: You couldn’t select and copy the code. And what good are code samples if you can’t do that (unless you’re the patient type who likes typing a lot). Vladimir Horbovanu had commented that he had modified the sample to be built on MVVM and added the option of selecting and even editing the text. However, this only supported C# and not VB, JS, Xaml, C++ and Xml as the original sample did, and there were a few issues with getting the text to properly align. However the “trick” he applied was simple but clever: Put a TextBox on top of the existing control, and make it transparent.

So I basically took Jeff’ awesome library, modified the template a bit, bound a TextBox with transparent text to the source code and put it on top of the existing template parts, tweaked the TextBox template to properly align and voila: The SyntaxHighlightingTextBlock is now a SyntaxHighlightingTextBox. I also added a couple of properties to the control to quickly get the selected text, set readonly state etc.

Jeff deserves most of the credit for this one, and Vladimir the rest for the neat TextBox trick. All I did was put it together, clean it up a bit and fix a couple of bugs in the highlighter. Expect to see this used in the next release of our SDK.

You can get the source here, and view the sample app here.

The library still only requires Silverlight 3, however the demo app uses Silverlight 4’ right-click feature for the context menu.

image

Update: Vlad took this sample further and improved rendering performance when editing larger amounts of code. See his updated blogpost here: http://www.vladhorby.com/blog/post/2010/11/01/code-editor-control-with-syntax-highlighting-for-silverlight-available.aspx
Isn't it great how the .NET community works together on building some useful stuff? Thanks Vlad!

Silverlight Behaviors, Triggers and Actions

My recent new love when doing Silverlight Development is Expression Blend’s Interactivity API that gives you some really neat support for attaching behaviors, triggers and actions to your elements, which in turn lets you structure your code better and allows you to reuse it more often (It boggles my mind why these are not part of core Silverlight).

You can download the Expression Blend SDK for free here, but you also get it with Expression Blend 3.0.

How often haven’t you done something like this:

<Button OnClick=”ShowToolsWindow” Content=”Show Tools” />

and in the code behind:

private void ShowToolsWindow(object sender, RoutedEventArgs e)
{
            ToolsWindow.Visibility = Visibility.Visible;
}

While this probably isn’t much code, imagine a whole toolbar or menu each with code in two places, and especially the code-behind more or less the exact same, but with a different target. And if I remove a button, I also have to remember to remove the eventhandler. Enter triggers and actions…

With the Expression SDK we can create a trigger that does this for us.

public class ToggleVisibilityAction : TargetedTriggerAction<UIElement>
{
	protected override void Invoke(object parameter)
	{
		this.Target.Visibility = 
			this.Target.Visibility == Visibility.Visible ?
				Visibility.Collapsed : Visibility.Visible;
	}
}

What this allows us to do is the following in xaml and without using any code-behind:

<Button Content="Show Tools" Margin="20" >
	<i:Interaction.Triggers>
		<i:EventTrigger EventName="Click" >
			<behaviors:ToggleVisibilityAction TargetName="ToolsWindow" />
		</i:EventTrigger>
	</i:Interaction.Triggers>
</Button>

While this might be a little more XAML than before, it cleanly separates the button into one little local piece, and also allows me to reuse the same behavior for multiple tools.

In the above case, I’m using a TargetedTriggerAction, meaning that it is triggered by one control, but acts on another. There are also non-targeted actions. For instance this one for toggling full screen:

public class ToggleFullScreenAction : TriggerAction<UIElement>
{
	protected override void Invoke(object parameter)
	{
		Application.Current.Host.Content.IsFullScreen = 
			!Application.Current.Host.Content.IsFullScreen;
	}
}
<Button Content="Toggle Fullscreen" >
	<i:Interaction.Triggers>
		<i:EventTrigger EventName="Click" >
			<behaviors:ToggleFullScreenAction />
		</i:EventTrigger>
	</i:Interaction.Triggers>
</Button>

Another more powerful item, is the behaviors. Behaviors allows us to add any logic to the control (or the application) it is attached to, when it gets attached. Basically there are two methods to override when creating a behavior: OnAttached and OnDetached. Usually this is where you will want to attach and detach eventhandlers to the element.

Here is one example that will hide an element if the application gets installed:

public class HideOnInstall : Behavior<UIElement>
{
	protected override void OnAttached()
	{
		base.OnAttached();
		Application.Current.InstallStateChanged += Current_InstallStateChanged;
	}

	protected override void OnDetaching()
	{
		base.OnDetaching();
		Application.Current.InstallStateChanged -= Current_InstallStateChanged;
	}

	private void Current_InstallStateChanged(object sender, EventArgs e)
	{
		this.AssociatedObject.Visibility = (Application.Current.InstallState == InstallState.Installed)
			? Visibility.Collapsed : Visibility.Visible;
	}
}

Now we can use that on our install button, so when the app has been installed, the button will automatically hide itself:

<Button Content="Install">
	<i:Interaction.Triggers>
		<i:EventTrigger EventName="Click" >
			<behaviors:InstallAction />
		</i:EventTrigger>
	</i:Interaction.Triggers>
	<i:Interaction.Behaviors> 
		<behaviors:HideOnInstall />
	</i:Interaction.Behaviors>
</Button>

A thing that has always bothered me is that the ScrollViewer control by default doesn’t listen to MouseWheel events. Delay recently blogged about adding smooth scrolling to the scroll viewer. Based on that, I changed this to be a behavior that listens to the MouseWheel event.

To do this we first create a behavior that inherits from Behavior<ScrollViewer>. This ensures that the behavior can only be attached to a ScrollViewer. In OnAttached we start listening for the MouseWheel event:

protected override void OnAttached()
{
       AssociatedObject.MouseWheel += AssociatedObject_MouseWheel;
       base.OnAttached();
}

In the event handler we just call AssociatedObject.ScrollToVerticalOffset(offset) to apply the scroll (The sample you can download here goes a little further and uses a DoubleAnimation with easing to make the scrolling more smooth). Now to add MouseWheel scrolling support to all scroll viewers, all you need to do is add the behavior to the scroll viewer:

<ScrollViewer>
	<i:Interaction.Behaviors>
		<behaviors:MouseScrollViewer />
	</i:Interaction.Behaviors>
</ScrollViewer>

The neat thing about these behaviors is that you get drag’n’drop behavior inside Expression Blend. This means that you can simply drag these from the Assets window right on to your elements without having to touch any code or XAML. Here’s what my sample application looks like in the objects and assets windows:

image

When I migrated this application from Silverlight 2 to 3, I managed to remove almost 70% of the code-behind in page.xaml.cs mostly caused by reusing simple actions and behaviors, and separating the logic into reusable classes instead. Later I found myself often going back to grab these classes and re-use them for other projects.

You can try out the sample application here and download the code here.

ESRI ArcGIS Silverlight/WPF API released

Last week we finally released v1.0 RTW of our Silverlight/WPF API. Today at our User Conference in San Diego, Jack Dangermond announced, that it even will be free for non-commercial use. The API will run on both v2 and v3 of Silverlight.

Furthermore today we released the entire source code for the toolkit assembly on CodePlex: http://esrisilverlight.codeplex.com

Also today at the Windows Partner Conference, we announced MapIt, a mapping solution running on a combination of SQL Server 2008, IIS and Silverlight/WPF and also with integration into Sharepoint. You can download a free 60-day evaluation of MapIt today. I encourage you to go see some of the demonstration videos – especially if you are new to GIS, this video could be an eye-opener to what information is hidden in your existing business intelligence.

If you are at the ESRI User Conference this week, come by the Silverlight Island in the showcase area and talk some Silverlight. I’ll be there most of the time Tuesday through Thursday. I’ll also be joining Rex Hansen and Art Haddad at the .NET SIG Tuesday evening, and the Silverlight intro sessions Wednesday and Thursday. Also watch Rich’s Demo Theater session which will demonstrate the ESRI Map Web Part for SharePoint and MapIt (the title on this session is incorrect).

Silverlight 3 Released

Silverlight 3 RTW is finally out !

Find the downloads here:

Expression Blend 3 with Sketchflow

Silverlight 3 Software Development Kit (SDK)

Silverlight 3 Tools for Visual Studio 2008 SP 1

or just go here to install the plugin: http://www.microsoft.com/silverlight/resources/install.aspx

While most of the new SL3 features has already been announced with the beta release, below are some of the new stuff that wasn’t available in the beta.

Mouse Wheel support !

We finally get native mouse wheel support with Silverlight 3. This means support for wheel in full screen, out of browser, when the DOM bridge is disabled, and most importantly no more ugly JavaScript hacks to get this working. The API is exactly the same as in WPF.

image 

 

Multi Touch Support.

Scott Guthrie announced this feature a few months ago, but it wasn’t included in the beta. Below is what this new API looks like:

image

Compared to the Surface API it looks like a fairly low-level version. The touch points you get will tell you if the user started touching, let go or is moving the finger, and also has methods for getting the element that is directly under the touch point. It’s up to the developer to then convert these gestures to something meaningful. The new behaviors API might come in handy for streamlining this.

Our prototype lab has already created some cool demos using Microsoft’s Surface table and our WPF API, and hopefully we can easily extend that to our Silverlight API as well.

 

Support for Alpha in 8bit PNG.

To me this is huge! We can finally start optimizing the download size by using PNG8 images and still have an alpha channel. Unfortunately Microsoft forgot 1, 2 and 4 bit, which a lot of optimized PNGs end up being. Hopefully that’ll come in a later version (judging from the PNG spec, there really isn’t much difference between 1, 2, 4 and 8 bits).

Out of browser changes

Out of browser configuration has been changed, and can now be configured using the UI tool in Visual Studio project properties:

image

Clear-type support

All browsers now get clear-type rendering of fonts.

Adding right click to Silverlight

In an earlier post, I created a small extension library that added several mouse gestures to Silverlight. However, the right-click only worked in Internet Explorer, and the solution was a bit of a hack. So to continue down the road of hacks, I found that there is a way to prevent the Silverlight Plugin from getting the right click event. By inserting a <div> on top of the plugin when the right mousebutton down event fires, you can prevent the mozilla browsers from getting the rightclick event. The mouseup event is then fired on this overlay div, and we remove the overlay again when the button is released or the mouse moves. Ugly but it works... The approach still requires the plugin to run in windowless mode.

Of course whether you even should be preventing the user from getting to the silverlight context menu in the first place is a whole different discussion.

I've updated the demo page, source and binary:

Try a demo!

Download binary (7 kb)

Download source (25 kb)