Thursday, 30 June 2011

How to create a Google Chrome extension

This simple example serves to show how you can create your own bespoke Goggle Chrome extension using HTML, Javascript and JSON.

With Extension Installed

When our extension is installed it displays an icon to the left of the favourites star in the URL box (our icon in this case is a blue square with 3D style glasses) and shows a JavaScript alert to the user if the tab is browsing my website http://stevenhollidge.com.

ScreenShot043

There are two types of extensions:

  Browser Extension (notice the icons to the right of the URL box, these browser extensions run all the time)

  Page Action (which is what this example happens to be)

The source code consists of a JSON manifest file, an HTML file containing some JavaScript and three icons:

ScreenShot045

Step 1: Download and Install Google Chrome for Developers

Step 2: Create manifest.json file

Create an empty folder then add a file called manifest.json, here’s my version:

Step 3: Add background.html file

Step 4: Add your icon files

Step 5: Upload your extension to Chrome

Open Chrome and navigate to Chrome://extensions, then click the “Load unpacked extension…” button and select the folder containing your extension files.

ScreenShot042

Debugging your extension

You can debug your Chrome extension by navigating to chrome://extensions (see screenshot above) and click the background.html link below Inspect active views which will open Google Developer Tools where you can place breakpoints to step through your code:

ScreenShot048

You can download the source code here:

http://stevenhollidge.com/blog-source-code/ChromeExtension-CheckForMyWebsite.zip

Sunday, 19 June 2011

Silverlight Debugging Tools

Here’s some of the tools I use to debug my Silverlight Out of Browser applications and track memory consumption for Silverlight applications. 
When the app starts up the user is shown the login screen.  In the background, whilst the user logs in, various xap files are being downloaded asynchronously.
ScreenShot034

Here’s how the tools look on start up of the application, note no Xap optimisation tools or minifiers have been used.


HTTP Traffic


Fiddler (free)

This tool is pretty common among all web devs and tracks HTTP traffic.  From this screenshot (tracking the startup of the application) we can see various external xap file requests are made to the localhost.
ScreenShot033

XAML and Resources


Silverlight Spy (commercial)

ScreenShot037

Memory Analysis


VMMap (free as part of SysInternals Tools Suite)


Select the process, in this case sllauncher.exe as it’s an out of browser application.

ScreenShot035
Here we can see the memory used by the application:
Heap – Native heap usage
Managed Heap – Silverlight and CLR heap memory usage
Image – Modules loaded
Stack – Silverlight and CLR stack memory usage
ScreenShot036

Visual Studio 2010 Profiling (Ultimate SKU)


Memory Profiling


ScreenShot038

CPU Profiling
ScreenShot039

WinDbg + SoS (Son of strike)

To be updated.

dotNet memory profiler (commercial)

To be updated.

CLR Profiler for Silverlight 4 and .NET 4 (free)


To be updated.


XPerf / HeapMonitor cmd –p %pid%

For native / unmanaged memory, to be updated.

Mike Cook is one of the leading authorities on Silverlight performance and someone to closely follow.


You can find his list of Silverlight best practises here:


http://blogs.msdn.com/b/slperf/p/resources.aspx

Dynamic UI in Silverlight

Sometimes you may need a UI that’s dynamically loaded perhaps from meta data stored in a database or some other repository.  There are two ways to do this in Silverlight code:

1) Create the .Net objects and attach them to the relevant LayoutRoot

2) Create a block of raw Xaml and load that into the relevant LayoutRoot

Here’s an example of a page that can use both methods to produce a simple bar chart:

ScreenShot019

Perhaps this is not the most visually stunning example but you can apply this technique to dynamically build your UI forms with textboxes and combos in a similar fashion to MVC scaffolding.

The Code

To download the source code click here:

http://stevenhollidge.com/blog-source-code/SilverlightDynamicUI.zip

Saturday, 18 June 2011

Composite apps with Prism

In this example I have used Prism to dynamically load xap files in the background after the initial landing page has loaded.

ScreenShot015

Here’s the same page with the Prism xap loader log switched on and configured to output to the screen.  You can see messages updating the developer on the sequence of operations such as the creation of the Unity container and tracking for each of the separate xap modules throughout their download and initialisation.

ScreenShot014

The application shell or display is broken down into three areas: 

The header

Containing the Company/Product name along with some user buttons for comments, settings, user details, log out and help.  This header is initially collapsed for the login screen and is made visible once the user successfully logs in.

Main content pane

In the example below the charts section has been selected from the main menu and displayed.

The footer

The footer contains the main menu to allow the user to load the content pane with various areas of functionality.  This section is also initially collapsed until the user has logged in.

Note in the screenshot below the logger output to screen has been switched off.

ScreenShot017

The XAPs

Each of the menu options is broken out into it’s own Xap file (separate Silverlight project) and can have their entry point / initial view loaded into the content pane via the messaging architecture.  Event the menu itself is a xap file that is loaded asynchronously whilst the user is preparing to login.

You can download the source for this code here:

http://stevenhollidge.com/blog-source-code/Silverblade-Prism.7z

Thursday, 16 June 2011

Agile RESTful Json in Silverlight

Following on from my previous post (Consuming POX in Silverlight), here’s a simple example of consuming a Json data service.

ScreenShot012

Data file (exposed via Http Handler on Web Server)

[
{
name:'Shredded Wheat',
price:4.95,
description:'Two per serving with skimmed milk',
calories:650
},
{
name:'Fresh Fruit Salad',
price:5.95,
description:'Strawberries, bananas, apples and pears',
calories:400
},
{
name:'Scrambled Eggs on Toast',
price:3.95,
description:'Two eggs on two slices of wholewheat toast',
calories:300
},
{
name:'Bacon Roll',
price:2.5,
description:'Three slices of lean bacon in a granary roll',
calories:600
},
{
name:'Homestyle Breakfast',
price:12.95,
description:'Two eggs, bacon, sausage, toast and orange juice',
calories:950
}
]

Http Handler (on Web Server)

using System.IO;
using System.Web;

namespace AgileREST.Web
{
public class FoodService : IHttpHandler
{

public void ProcessRequest(HttpContext context)
{
var dataPath = HttpContext.Current.Server.MapPath("Food.json");

using (var reader = new StreamReader(dataPath))
{
var result = reader.ReadToEnd();
context.Response.ContentType = "text/json";
context.Response.Write(result);
}
}

public bool IsReusable
{
get
{
return false;
}
}
}
}

Mapping (on the client)

namespace AgileREST
{
public class Food
{
public string Name { get; set; }
public decimal Price { get; set; }
public string Description { get; set; }
public int Calories { get; set; }
}
}

Service Call (on the client)

using System;
using System.Collections.Generic;
using System.Json;
using System.Linq;
using System.Net;
using System.Runtime.Serialization.Json;
using System.Windows;
using System.Windows.Browser;
using System.Windows.Controls;

namespace AgileREST
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}

void webClientForJson_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
if (e.Error != null) return;

// first option
JsonArray foods = (JsonArray)JsonArray.Load(e.Result);
var query = from food in foods
select new Food()
{
Name = (string)food["name"],
Price = (decimal)food["price"],
Description = (string)food["description"],
Calories = (int)food["calories"]
};
listboxFoodJson.ItemsSource = query.ToList();

// second option
// for implicit serialisation requires identical case sensitive name across Json and C# food objects)
//DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(List<Food>));
//List<Food> foods = (List<Food>) jsonSerializer.ReadObject(e.Result);
//listboxFoodJson.ItemsSource = foods;
}

private void btnGetFoodJson_Click(object sender, RoutedEventArgs e)
{
WebClient webClientForXml = new WebClient();
webClientForXml.OpenReadCompleted += webClientForJson_OpenReadCompleted;
webClientForXml.OpenReadAsync(new Uri(HtmlPage.Document.DocumentUri, "FoodService.ashx"));
}
}
}

Data binding (on the client)

<UserControl x:Class="AgileREST.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="700">

<UserControl.Resources>
<DataTemplate x:Key="itemTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="tbName"
Width="170"
Text="{Binding Path=Name}" />
<TextBlock x:Name="tbPrice"
Width="50"
Text="{Binding Path=Price}" />
<TextBlock x:Name="tbDescription"
Width="300"
Text="{Binding Path=Description}" />
<TextBlock x:Name="tbCalories"
Width="50"
Text="{Binding Path=Calories}" />
</StackPanel>
</DataTemplate>
</UserControl.Resources>

<Grid x:Name="LayoutRoot" Background="White">
<StackPanel Width="600" Margin="10">
<TextBlock Text="Json Example" Margin="5" />
<StackPanel x:Name="ColumnDescriptions" Orientation="Horizontal" Margin="5" >
<TextBlock Text="Name" Width="170" />
<TextBlock Text="Price" Width="50" />
<TextBlock Text="Description" Width="300" />
<TextBlock Text="Calories" Width="50" />
</StackPanel>
<ListBox x:Name="listboxFoodJson"
Height="150"
Margin="5"
ItemTemplate="{StaticResource itemTemplate}" />
<Button x:Name="btnGetFoodJson"
Height="50"
Margin="5"
Click="btnGetFoodJson_Click"
Content="Get Food From Json Service" />
</StackPanel>
</Grid>
</UserControl>

You can download the source code from the following link:


http://stevenhollidge.com/blog-source-code/AgileREST.zip

Consuming POX in Silverlight

We have the simple scenario of a web server exposing a menu data as plain old xml (POX).  Our Silverlight application would like to consume this data and display it in a simple list box. 

Here’s how it’s done:

ScreenShot010

Data file (directly exposed on web server)

Mapping (on client)

Service Call (on client)

Data Binding (on client)

It’s as easy as that.

You can download the source code here:

http://stevenhollidge.com/blog-source-code/SilverlightXmlService.zip

Wednesday, 15 June 2011

Ribbon control in Silverlight

It’s been five years since Microsoft introduced the Ribbon within Office but it still divides opinion.  Here’s my sample app using a navigation frame and the Ribbon control from third party control vendor DivElements.

ScreenShot009

This example uses WCFRIA Services so you’ll need that installed (VS SP1 includes WCFRIA Services).

You might also want to install the latest Ribbon Dlls which can be downloaded from the Div Elements website:

http://www.divelements.co.uk/net/controls/sandribbonsl/

To download the code click here):

http://stevenhollidge.com/blog-source-code/RibbonDemo.zip

NOTES:

v2 of the Ribbon Dll is included in the Libs folder of the source if you haven’t downloaded the Ribbon Dlls, just update the reference in the Silverlight project.

As you are downloading Dlls from the web you’ll need to “unblock” them by opening Windows Explorer and right clicking on each file, select properties and click unblock.

You will need to update the Sql Server connection details in the web.config file to point to a database with ASPNET security tables loaded.

Don’t forget to set SilverbladeDemo.Web as the start up project and Index.html as the startup page.

TreeView menu for Silverlight

Here’s a little example app that I knocked up to showcase a TreeView control used as a menu to update the navigation frame on the right hand side.

ScreenShot008

You can download the integrated solution source here:

http://www.stevenhollidge.com/blog-source-code/Silverblade5-WCF-RIA-MVVMLight-Messenger.zip

Tuesday, 14 June 2011

Xaml in Windows 8

Some interesting developments in the investigations of the Windows 8 Milestone 3 build.

It would appear Jupiter, the next gen WPF/SL xaml language will sit on top of DirectUI, which will render your output (windows, borders, labels, graphics etc) to the screen.

330fv431

I’m sure they’ll be plenty of rumours and leaks leading up to Build in September but for now it looks like a message of long live Xaml! Smile

Monday, 13 June 2011

The start of Footy News on Windows Phone 7

So here’s a quick recap of where we are:

  • We’ve got a service running on the Azure platform that trawls the net for the latest footy news via various sporting RSS feeds
  • Back end storage in the cloud via SQL Azure for the footy articles
  • Hosting in the cloud via Windows Azure for an ASP.NET website to check the service is running and that our service is actively grabbing the latest articles  http://footy.cloudapp.net

The next step is to build a WP7 app that will read from SQL Azure and display the footy news.  My initial prototype simply lists the articles on the left hand side and allows the user to select and swipe to the right to view the article on the web. 

Here’s a screencast of the quick prototype written in Silverlight:

The start of the Footy News WP7 Prototype from Steven Hollidge on Vimeo.

Azure

I’ve written a little application that trawls the internet for footy gossip so that users can have a one stop shop for all the latest rumours. 

The solution is pure C# and Azure. The website is hosted on Windows Azure, the data is stored on SQL Azure and the service that trawls the RSS feeds is running on Azure.

Here’s a screenshot:

ScreenShot002

You can hit the live site by clicking on the following link:  http://footy.cloudapp.net/

The application reads various sports RSS feeds and stores the title and links to the articles within SqlAzure (note: I’ve hidden some sensitive data):

ScreenShot004

To view one the feeds click on the this link from The Mirror newspaper in the UK:

http://www.mirror.co.uk/sport/football/rss.xml

Seeing as I’ve got this week off work I’m thinking about knocking up a Silverlight application to deploy to WP7 (Windows Phone).  The tricky part is I don’t own a Windows Phone so testing might be tough.  I’ll give it a go and write a blog post on my learnings.  Here’s hoping Mango is as good as the Microsoft sales team say it is!

Sunday, 12 June 2011

IntelliTrace with VS 2010 Ultimate

IntelliTrace collects information whilst your application is running so you, as a developer, can rerun through the code flow to identify and debug exceptions.

Here’s how to switch IntelliTrace on:

Tools > Options > IntelliTrace, then select Enable IntelliTrace:

IntelliTrace

You can see now when we run through our sample app, the IntelliTrace has tracked all the input parameters for each of the methods so we can step back in time to a previous method.

There are two views in IntelliTrace, the first being “Calls View” which we can see here listed on the right hand side (notice all the input variables are traced).

IntelliTrace2

Below we have stepped back in time to Level2, notice local variables weren’t stored here but you can still step through the code flow.

IntelliTrace3

We are going to add additional events to the default traced events, by returning to Tools > Options > IntelliTrace section and selecting IntelliTrace Events adding Console.

IntelliTrace4

Now with Console added, in the “Events View” the Console Events are being tracked.

IntelliTrace5

This is a useful technology that can be switched on in production to store traces that can be replayed back on a development machine, but under the environment of production.

In this example I’ve stored the trace file in the default location, this time set under Tools > Options > IntelliTrace > Advanced section.

IntelliTrace5b

Generates a file each time the application is run.

IntelliTrace5a

Now you can close Visual Studio 2010 completely and replay the code any time in the future on whatever machine you like.  Open the iTrace file in Visual Studio 2010 Ultimate and you can see the environment settings, DLLs loaded including version ids, all the call and event tracing info.

IntelliTrace6

The threading view is particularly good for seeing multi threaded apps and also garbage collection threads kicking in.

IntelliTrace7

IntelliTrace is currently only available on Visual Studio 2010 Ultimate but I think it will be included in lower level SKUs in future versions of Visual Studi0.  Fingers crossed for VS 2012.

Introduction to MongoDb

MongoDb is a scalable, high-performance, open source, document-oriented database written in C++. 

From C#, it’s really easy to store your POCO objects as a document within Mongo.  Internally to MongoDb stores documents as BSON (binary JSON) but as we’re using the C# MongoDb driver we can use our native POCOs. 

Here's the simple POCO objects we'll be using:

It’s simple to connect to a database:

Here's an example of adding two asset documents:

 

To remove all the documents from a collection:

MongoDb is a free and open source project, to install simply download the binaries http://www.mongodb.org/downloads

Extract the binaries to C:\MongoDb, create a subfolder called Data then open command prompt and run the following command:

ScreenShot086

MongoDb is now running so we can interact with our database.  Note: In production you can run MongoDb as a service using the “–service” switch.

ScreenShot087

You can download the source code from this sample here:

http://stevenhollidge.com/blog-source-code/MongoDbSample.zip

Friday, 10 June 2011

Updating Silverlight OOB Applications

In Silverlight Out Of Browser applications (OOB), it’s easy to give ClickOnce style new version updates to deployed apps.  Just add the following code to your App.xaml.cs file:

public App()
{
this.Startup += this.Application_Startup;

InitializeComponent();

if (!Application.Current.IsRunningOutOfBrowser) return;

Application.Current.CheckAndDownloadUpdateCompleted += this.CheckAndDownloadUpdateCompleted;
Application.Current.CheckAndDownloadUpdateAsync();
}

new void CheckAndDownloadUpdateCompleted(object sender, CheckAndDownloadUpdateCompletedEventArgs e)
{
if (e.Error == null && e.UpdateAvailable)
{
MessageBox.Show("Application updated, please restart to apply changes.");
}
}

private void Application_Startup(object sender, StartupEventArgs e)
{
this.RootVisual = new MainPage();
}

To show this working, I’ve created an app that simply displays it’s current version (set in the Properties/AssemblyInfo.cs file.


ScreenShot081


Here’s the code behind for the MainPage.xaml.cs:

using System;
using System.Reflection;
using System.Windows.Controls;

namespace UpdatingOOB
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();

Assembly assembly = Assembly.GetExecutingAssembly();
var assemblyName = new AssemblyName(assembly.FullName);
Version version = assemblyName.Version;

tbVersionInfo.Text = string.Format("Version: {0}.{1}.{2}.{3}",
version.Major,
version.Minor,
version.Build,
version.Revision);
}
}
}

Change code (or just the version number), rebuild your Silverlight app source code and re-run your Silverlight host web project to push your updated xap file to the host.


Now when you run your Silverlight OOB application the update is detected and message displayed.


ScreenShot082


When you restart the Silverlight OOB the new version runs.


ScreenShot083


You can download the code here:


http://stevenhollidge.com/blog-source-code/UpdatingOOB.zip

Thursday, 9 June 2011

Silverlight Image Reflections

It’s really easy to use image reflections in Silverlight and here’s an example:

ScreenShot076

You simply use two image controls one for the main image and one for the mirror image.  Set the mirrored image opacity (the closer to zero the more see through), RenderTransformOrigin sets the location beneath the original image and to flip the image just use ScaleTransform ScaleY="-1".

Here’s the code:

Here’s a link to download the source code for this example:

http://stevenhollidge.com/blog-source-code/Reflections.zip

Wednesday, 8 June 2011

Silverlight High Frequency Services

I’ve written a quick Silverlight application that listens to a WCF Service streaming a fire hose of the latest Fx prices at a rate of 1,200 per minute.

The application showcases the MVVM pattern, makes use of MVVMLight Toolkit and features the cosmopolitan/metro theme.

ScreenShot072_thumb[5]

The Service

The WCF service exposes a pub/sub model with a call back for each new FX Rate price:

using System;
using System.ServiceModel;
using System.Threading;
using System.Threading.Tasks;

namespace PricingServiceHost
{
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class PricingService : IPricingService
{
static PricingService()
{
Task.Factory.StartNew(() =>
{
var factory = new PriceFactory();
while (true)
{
Thread.Sleep(50);
if (PriceUpdate == null) continue;
FxRate latestPrice = factory.GetNextPrice();

PriceUpdate(
null,
new PriceUpdateEventArgs
{
LatestPrice = latestPrice
});
}
});
}

static event EventHandler<PriceUpdateEventArgs> PriceUpdate;

IPricingServiceCallback _callback;

public void Subscribe()
{
_callback = OperationContext.Current.GetCallbackChannel<IPricingServiceCallback>();
PriceUpdate += PricingService_PriceUpdate;
}

public void UnSubscribe()
{
PriceUpdate -= PricingService_PriceUpdate;
}

void PricingService_PriceUpdate(object sender, PriceUpdateEventArgs e)
{
if (((ICommunicationObject)_callback).State == CommunicationState.Opened)
{
try
{
_callback.PriceUpdate(e.LatestPrice);
}
catch
{
UnSubscribe();
}
}
else
{
UnSubscribe();
}
}
}
}


The Model (M)

using System;
using System.Collections.ObjectModel;
using GalaSoft.MvvmLight;

namespace MetroPricingSample.Models
{
public class DisplayFxRate : ObservableObject
{
public static ObservableCollection<DisplayFxRate> InitialRates = new ObservableCollection<DisplayFxRate>
{
new DisplayFxRate("AUD", (decimal) 0.93272),
new DisplayFxRate("BRL", (decimal) 1.58100),
new DisplayFxRate("CAD", (decimal) 0.97495),
new DisplayFxRate("CHF", (decimal) 0.83603),
new DisplayFxRate("CNY", (decimal) 0.15425),
new DisplayFxRate("EUR", (decimal) 0.68103),
new DisplayFxRate("GBP", (decimal) 0.60819),
new DisplayFxRate("INR", (decimal) 44.6300),
new DisplayFxRate("JPY", (decimal) 80.0032),
new DisplayFxRate("NZD", (decimal) 1.21847),
new DisplayFxRate("RUB", (decimal) 27.7411),
new DisplayFxRate("THB", (decimal) 0.03303),
new DisplayFxRate("ZAR", (decimal) 6.71610)
};

public DisplayFxRate() { }

public DisplayFxRate(string isoCode, decimal rate)
{
IsoCode = isoCode;
PreviousRate = rate;
CurrentRate = rate;
Updated = DateTime.Now;
}

public const string IsoCodePropertyName = "IsoCode";
private string _isoCode = string.Empty;
public string IsoCode
{
get { return _isoCode; }

set
{
if (_isoCode == value) return;
_isoCode = value;
RaisePropertyChanged(IsoCodePropertyName);
}
}

public const string PreviousRatePropertyName = "PreviousRate";
private decimal _previousRate = 0;
public decimal PreviousRate
{
get { return _previousRate; }

set
{
if (_previousRate == value) return;
_previousRate = value;
RaisePropertyChanged(PreviousRatePropertyName);
}
}

public const string CurrentRatePropertyName = "CurrentRate";
private decimal _currentRate = 0;
public decimal CurrentRate
{
get { return _currentRate; }

set
{
if (_currentRate == value) return;

_previousRate = _currentRate;
_currentRate = value;

RaisePropertyChanged(PreviousRatePropertyName);
RaisePropertyChanged(CurrentRatePropertyName);
RaisePropertyChanged(DeltaPropertyName);
RaisePropertyChanged(StatusPropertyName);
}
}


public const string DeltaPropertyName = "Delta";
public decimal Delta
{
get
{
decimal result;

if (PreviousRate == 0 || CurrentRate == 0)
result = 0;
else
result = Math.Round(((CurrentRate / PreviousRate) - 1), 2);

return result;
}
}

public const string StatusPropertyName = "Status";
public Status Status
{
get
{
Status status;
var delta = Delta;

if (delta > 0)
status = Status.Increase;
else if (delta < 0)
status = Status.Decrease;
else
status = Status.NoChange;

return status;
}
}

public const string UpdatedPropertyName = "Updated";
private DateTime _updated = DateTime.MinValue;
public DateTime Updated
{
get { return _updated; }

set
{
if (_updated == value) return;
_updated = value;
RaisePropertyChanged(UpdatedPropertyName);
}
}
}
}


The View (V)

<navigation:Page x:Class="MetroPricingSample.Views.Pricing"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
xmlns:Converters="clr-namespace:MetroPricingSample.Converters"
d:DesignHeight="300"
d:DesignWidth="640"
DataContext="{Binding PricingViewModel, Source={StaticResource Locator}}"
Style="{StaticResource PageStyle}"
mc:Ignorable="d">
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="60" />
<RowDefinition Height="30" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.Resources>
<Converters:BoolToSubscribedTextConverter x:Key="BoolToSubscribedTextConverter" />
<Converters:StatusToIconConverter x:Key="StatusToIconConverter" />
<Converters:IsoCodeToFlagConverter x:Key="IsoCodeToFlagConverter" />
<Converters:DateTimeToTimeConverter x:Key="DateTimeToTimeConverter" />
</Grid.Resources>

<StackPanel Grid.Row="0">
<Button x:Name="btnSubscribe"
Width="200"
Height="30"
HorizontalAlignment="Left"
Content="{Binding Subscribed, Converter={StaticResource BoolToSubscribedTextConverter}}"
Command="{Binding SubscriptionCommand, Mode=TwoWay}" />
<TextBlock x:Name="tbInfo" Height="30" Text="{Binding ErrorText}"/>

</StackPanel>
<StackPanel Grid.Row="1" Orientation="Horizontal">
<TextBlock Text="Currency" Width="85" Margin="10,0,0,0"/>
<TextBlock Text="Previous" Width="100"/>
<TextBlock Text="Current" Width="100" />
<TextBlock Text="Delta" Width="160" />
<TextBlock Text="Updated" />
</StackPanel>
<ListBox x:Name="lbFxRates"
ItemsSource="{Binding Path=Rates}"
Grid.Row="2">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding IsoCode, Converter={StaticResource IsoCodeToFlagConverter}}" Width="20" Margin="10,0,0,0"/>
<TextBlock Text="{Binding IsoCode}" Width="50" Margin="10,0,0,0"/>
<TextBlock Text="{Binding PreviousRate}" Width="100" />
<TextBlock Text="{Binding CurrentRate}" Width="100" />
<TextBlock Text="{Binding Delta}" Width="100" HorizontalAlignment="Right" Margin="0,0,10,0" />
<Image Source="{Binding Status, Converter={StaticResource StatusToIconConverter}}" Width="20" />
<TextBlock Text="{Binding Updated, Converter={StaticResource DateTimeToTimeConverter}}" Width="200" Margin="30,0,0,0" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</navigation:Page>


The View Model (VM)



The view model in the client currently uses a generated proxy for the WCF service, we I really don’t like, this will be removed in the next refactoring iteration.

using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Input;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using MetroPricingSample.Models;
using MetroPricingSample.ServiceReference1;

namespace MetroPricingSample.ViewModels
{
public class PricingViewModel : ViewModelBase
{
public ObservableCollection<DisplayFxRate> Rates { get; set; }

private const string SubscribedPropertyName = "Subscribed";
private bool _subscribed = false;

public bool Subscribed
{
get { return _subscribed; }

set
{
if (_subscribed == value)
{
return;
}

_subscribed = value;
RaisePropertyChanged(SubscribedPropertyName);
}
}

private const string ErrorTextPropertyName = "ErrorText";
private string _errorText = string.Empty;

public string ErrorText
{
get { return _errorText; }

set
{
if (_errorText == value)
{
return;
}

_errorText = value;
RaisePropertyChanged(ErrorTextPropertyName);
}
}


public ICommand SubscriptionCommand { get; set; }

private bool _subscriptionCommand_CanExecute = true;

private PricingServiceClient _client;

public PricingViewModel()
{
Rates = DisplayFxRate.InitialRates;

if (IsInDesignMode) return;

_client = new PricingServiceClient();
_client.SubscribeCompleted += _client_SubscribeCompleted;
_client.UnSubscribeCompleted += _client_UnSubscribeCompleted;
_client.PriceUpdateReceived += PriceUpdate;
SubscriptionCommand = new RelayCommand(SubscriptionCommand_Execute, () => _subscriptionCommand_CanExecute);
}

void SubscriptionCommand_Execute()
{
if (!Subscribed)
{
_client.SubscribeAsync();
}
else
{
_client.UnSubscribeAsync();
}

_subscriptionCommand_CanExecute = false;
}

void _client_UnSubscribeCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
if (e.Error == null)
{
Subscribed = false;
ErrorText = "";
}
else
{
ErrorText = "Unable to connect to service.";
}

_subscriptionCommand_CanExecute = true;
}

void _client_SubscribeCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
if (e.Error == null)
{
Subscribed = true;
ErrorText = "";
}
else
{
ErrorText = "Unable to connect to service.";
}

_subscriptionCommand_CanExecute = true;
}

public void PriceUpdate(object sender, PriceUpdateReceivedEventArgs e)
{
if (Subscribed)
{
PriceUpdate(e.fxRate);
}
}

public void PriceUpdate(FxRate fxRate)
{
try
{
foreach (var rate in Rates.Where(rate => rate.IsoCode == fxRate.IsoCode))
{
rate.CurrentRate = fxRate.Rate;
rate.Updated = fxRate.Updated;
}
}
catch (Exception e)
{
//log here
}
}
}
}


Conclusion



The application currently uses MVVM Light on the client side and WCF for the server side service.  The GUI is struggling to keep up with the service so I plan to introduce the Telerik Grid Control to see how it deals with the updates.  The functionality currently provided by value converters will be moved out of the view and into the view model and I’ll also refactor the application to use a REST interface with Service Stack (written by Demis Bellot).



You can download the source code here:



https://github.com/stevenh77/MetroPricingSample



When you run the application, be sure to set the Web host and Service to both start up at runtime (right click on solution > Properties > Multiple Startup Projects > START both MetroPricingSample.Web and PricingServiceHost).



Note: As I’m looking purely at performance I’ve deliberately omitted tests and some of the error handling and graceful dereferencing, I’ll add these as I refactor later on.

Sunday, 5 June 2011

Metro / Zune style Silverlight assets

Metro and Zune give a modern look and feel to your apps.  Here are a couple of examples of how to implement the look within your Silverlight application.

 

mycw

When compared to a default pop up window I think you’ll agree the Zune style is more impressive.

cw1

Here’s the default context menu:

DefaultContextMenu

Now here’s the Silverlight context menu compared to the Zune menu.

FinalContextMenus

These assets are available from Jeff Wilcox – good job Jeff!

http://www.jeff.wilcox.name/2010/05/my-childwindow-design/

http://www.jeff.wilcox.name/2010/05/zunelike-contextmenu-style/

Friday, 3 June 2011

Natural User Interface

I’m really excited about the possibilities around touch, gestures and the Kinect.  NUI could dramatically change our working and home environments and really take us into the future.

Developers will need to be brave and bold, innovation will be king.

A Day Made of Glass

 

Microsoft UX: What Just Happened

Great little slideshow from a talk given by former Silverlight product manager Scott Barnes in Feb 2010. Interesting with all the recent developments for Windows 8 embracing touch with native HTML5 + JS.

Thursday, 2 June 2011

Demystifying WCF RIA Services Part 2

Following on from Part 1, we’ll now add insert, update and delete methods to our WCFRIA domain service.

Update your PersonService.cs class as follows:

Note I’m using attributes here to explicitly define the operations for Insert, Update and Delete.  I could have left these off as WCFRIA Services picks up Insert/Create/Add within the method for Insert, Update/Edit and Updates and Remove/Delete for deletions but I prefer to keep things explicit.

We are also overriding the Submit method here, which isn’t required but get’s called by the client proxy and passes back the changed item set before each of the the insert/update/delete methods are called for the individual changed items.

We'll keep the GUI real simple with just a datagrid, save button and status textblock but you'll see how powerful the grid is shortly: MainPage.xaml

Finally update your code behind on the server, note the callback methods for each of the service calls.  Remember all service calls are async in Silverlight and I reckon including the call back methods to response to any errors that might have occurred during the service call: MainPage.xaml.cs

On start up our service loads the data grid with data:

ScreenShot066

As our generated strongly typed Person object knows an Age is both required and an integer, the data grid automatically picks up the validation notifications and displays them to the user.

ScreenShot067

When we update the data with valid info and click save our success message shows us our service call encountered no errors.

ScreenShot068

The source code for this project can be downloaded here:

http://stevenhollidge.com/blog-source-code/WcfRiaWithPocos-part2.zip

Windows 8… it’s coming!

 

Wednesday, 1 June 2011

Demystifying WCF RIA Services Part 1

WCF RIA Services rock for RAD development of Silverlight apps!  Why?  Because the framework takes your basic services, applies magic and voodoo then BAM! your client has access to data bindable objects and the services to access and update them.

I’m a big fan of RAD and IDE magic but only when I know exactly what’s going on.

With this blog post I aim to pull back the curtain on that voodoo and help people to understand what’s going on under the covers.

First up create a normal Silverlight application, note we are starting from scratch and will not be using the WCF RIA Business application template:

ScreenShot052

Then add WCF RIA Services to the application:

ScreenShot053

Now add a Person class to your WcfRiaWithPocos.Web project:

ScreenShot054

We are now ready to add a domain service to our Web project.  This is the service that will be automagically hosted in a WCF service by the WCF RIA Services framework.

ScreenShot055

ScreenShot056

Press CTRL + SHIFT + B to build your project and voodoo will take place….

What’s happening is that WCFRIA Services takes a look at your Web project, notices the Domain Service exposes the Person object and will generate code on your client project.  To see the file in your solution explorer you’ll need to select the Silverlight client project (WcfRiaWithPocos) and select from the Visual Studio main menu in  Project > Show All Files.  You can then see the file here under the Generated_Code folder:

voodoo

Let’s take a look at what’s within this file – bear with me it’s a lot of code but I’ll explain each section shortly:

 

public sealed partial class WebContext : WebContextBase

The first section defines a WebContext class.  This object is used for authentication and to store the user and role info (current user context).

public sealed partial class Person : ComplexObject (upgradable to Entity)

The next section is our Person object.  You can see WCFRIA has created a new Person object that specialises from the abstract class ComplexObject.  This special class lives in the System.ServiceModel.DomainServices.Client namespace and implements the following interfaces:

public abstract class ComplexObject: INotifyDataErrorInfo, IEditableObject, INotifyPropertyChanged
Note that a ComplexObject differs from Entity abstract class used when Entity Frameworks are introduced (rather than POCOs in this example) in that your original class does not require a Key attribute.  This leads to some restrictions compared to the Entity in that Complex objects cannot be shared or referenced from multiple parent instances and they do not support inheritance.
public abstract class Entity : INotifyDataErrorInfo, IEditableObject, INotifyPropertyChanged, IRevertibleChangeTracking, IChangeTracking
To update your Person class to an Entity simply add an Id property to your Person class and give it a key attribute.  As we've noticed validation kicking in on our client side we'll also add a required attribute to the Age property.

Don't forget to update the service to include a key for each object:


You can see that the code generated on your client side is now deriving from an Entity and is still raising all the events required to enable data binding to occur including validation.


public sealed partial class PersonContext : DomainContext


The final section in the generated code is for the service.  This section creates a PersonContext class (swapping the word Service for Context), default access to the hosting, an interface IPersonServiceContract from our original DomainService, a container to access collections of “Person” and a method to query our exposed service.


PersonContext class


The DomainContext is the proxy to your services and is fully explained here:


http://msdn.microsoft.com/en-us/library/ee707370(v=vs.91).aspx


Default access to the hosted service:


Container for collection access


Access to our service endpoint:


IPersonServiceContract interface, note the async nature of this interface – all service calls in Silverlight are asynchronous:


Right now we understand what's been generated we're finally ready to make use of our service on the client


Add a listbox to the MainPage.xaml file for the Silverlight client:


Finally update the code behind to use the async method call on service proxy.


wcfria-final


In the second part of this blog article I’ll show how to improve the service to incorporate Add, Edit and Delete functionality.