Sunday, August 8, 2010

Single window F1 help in Silverlight

I know the title is confusing.You will know why I gave this title when you read further.When we talk about the Rich Internet Application we could see that they are half desktop and half web.The UI resembles a desktop application but they behave like web applications.

As we know all the desktop applications comes with a help.We all would like to have a help popup on F1 key when we are struck on a desktop’s functionality. The same applies to RIA.Due to its richness like desktop we should have a F1 help window.This post talks about implementing a F1 help window for Silverlight applications.

Basically we need to capture the F1 key and show a popup.I don’t think people expects a huge hlp file on F1 because this is web and downloading a big file will take time.So better we can choose html or asp.net based help which are context based and easy to load. Now the things are simple just show a html popup on F1 press.

Here I am adding one good feature of Silverlight.Attached properties. This extends one class by introducing a new property implemented in another class.I am not going into details of attached properties.We can write a HelpProvier class which holds the attached property so that we can set the help source as follows from anywhere in our application.

<UserControl x:Class="F1Help.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:F1Help">
<Grid x:Name="LayoutRoot" Background="White" local:HelpProvider.Source="help.htm">
<TextBox Text="Enter the datas here"></TextBox>
</Grid>
</UserControl>


Lets see how the HelpProvider is processing the F1 key.

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Browser;

namespace F1Help
{
public class HelpProvider
{
public static Uri GetSource(DependencyObject obj)
{
return (Uri)obj.GetValue(SourceProperty);
}
public static void SetSource(DependencyObject obj, Uri value)
{
obj.SetValue(SourceProperty, value);
}
public static readonly DependencyProperty SourceProperty =
DependencyProperty.RegisterAttached("Source", typeof(Uri), typeof(HelpProvider), new PropertyMetadata(OnSourcePropertyChanged));
public static void OnSourcePropertyChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (e.NewValue != null && e.NewValue is Uri)
{
FrameworkElement element = sender as FrameworkElement;
element.KeyDown+=new KeyEventHandler(element_KeyDown);
}
}
static void element_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.F1)
{
e.Handled = true;
e = null;
if (GetSource(sender as DependencyObject) != null)
{
ShowHelpFile(GetSource(sender as DependencyObject));
}
}
}
private static void ShowHelpFile(Uri source)
{
HtmlPage.Window.Navigate(source, "new");
}
}
}


The code is self explanatory.In the property changed method we are subscribing to the keydown event of the UIElement which requested help implementation.The event handler shows the htm file in a popup.Simple…

But you can see yourself this is not as simple as we thought when you run the app.F1 will show our help as well as browser help.The user needs our help only when he is in our application.So we need to avoid browser help at any cost.What to do? I know what everybody thinking as web developers.Yes Javascript…


function HideHelp() {
document.onhelp = function () { return (false); }
window.onhelp = function () { return (false); }
}


Call this function on document.onload.This is tested only in IE 8.Sample can be downloaded from here.