.NET Framework Bookmark and Share   
 index > Windows Presentation Foundation (WPF) > Context-Sensitive Help in WPF
 

Context-Sensitive Help in WPF

Context-sensitive help is a kind of online help that is obtained from a specific point in the state of the software, providing help for the situation that is associated with that state.
Context-sensitive help, as opposed to general online help or online manuals, doesn't need to be accessible for reading as a whole. Each topic is supposed to describe extensively one state, situation, or feature of the software.

Now the question is how to provide the context sensitive help in a WPF application.

The main idea is to simply use the built-in "ApplicationCommands.Help" command. This command is already tied to the F1 key, and so executes when you hit F1, and tells your command handler what element the user was on when it was hit.


Lets start to create an application in WPF.

<Windowx:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1"Height="144"Width="300">
<GridHeight="70"Width="268">
<Grid.ColumnDefinitions>
<ColumnDefinitionWidth="100"MinWidth="32"/>
<ColumnDefinitionWidth="175"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinitionHeight='auto'MinHeight="19"/>
<RowDefinitionHeight='auto'MinHeight="31"/>
</Grid.RowDefinitions>
<TextBlockMargin="0,5,5,0"Height="15"VerticalAlignment="Center">Enteryourname:</TextBlock>
<TextBoxGrid.Column='1'Name='NameField'Height="20"VerticalAlignment="Top"Margin="0,0,26,0"/>
<ButtonGrid.Row="1"Height="23"Margin="15,8,85,0"Name="Submit"VerticalAlignment="Top"Grid.Column="1">Submit</Button>
</Grid>
</Window>

Now we have a sample application with a test box and a button.

Now lets add a help provider class in the sample application.

You will need to add the reference of "System.Windows.Forms" in the sample application.

staticclassHelpProvider
{
publicstaticreadonlyDependencyPropertyHelpStringProperty=
DependencyProperty.RegisterAttached("HelpString",typeof(string),typeof(HelpProvider));
staticHelpProvider()
{
CommandManager.RegisterClassCommandBinding(typeof(FrameworkElement),new
CommandBinding(ApplicationCommands.Help,newExecutedRoutedEventHandler
(Executed),newCanExecuteRoutedEventHandler(CanExecute)));
}
publicstaticvoidSetHelpString(DependencyObjectobj,stringvalue)
{
obj.SetValue(HelpStringProperty,value);
}
staticprivatevoidCanExecute(objectsender,CanExecuteRoutedEventArgse)
{
FrameworkElementsenderElement=senderasFrameworkElement;
if(HelpProvider.GetHelpString(senderElement)!=null)
e.CanExecute=true;
}
publicstaticstringGetHelpString(DependencyObjectobj)
{
return(string)obj.GetValue(HelpStringProperty);
}
staticprivatevoidExecuted(objectsender,ExecutedRoutedEventArgse)
{
System.Windows.Forms.MessageBox.Show("Help:"+HelpProvider.GetHelpString(sender
asFrameworkElement));
}
}

Instead of putting the command handler in the Window, we'll put it in the HelpProvider itself. We can do this by registering a command handler directly against the FrameworkElement class; now we'll get called for any FrameworkElement instance in the application. We'll also register for the command's CanExecute handler. This allows us to decide if we should handle a command at an element, or let it bubble up to a higher handler. That is, this will allow the Help command to bubble up from AddressField, which has no HelpString, to Window which does.
Now lets add some help text to the text box and the button.

<Windowx:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1"Height="144"Width="300"
xmlns:h="clr-namespace:WpfApplication1">
<GridHeight="70"Width="268">
<Grid.ColumnDefinitions>
<ColumnDefinitionWidth="100"MinWidth="32"/>
<ColumnDefinitionWidth="175"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinitionHeight='auto'MinHeight="19"/>
<RowDefinitionHeight='auto'MinHeight="31"/>
</Grid.RowDefinitions>
<TextBlockMargin="0,5,5,0"Height="15"VerticalAlignment="Center">Enteryourname:</TextBlock>
<TextBoxGrid.Column='1'Name='NameField'Height="20"VerticalAlignment="Top"Margin="0,0,26,0"
h:HelpProvider.HelpString="Enteryourname."/>
<ButtonGrid.Row="1"Height="23"Margin="15,8,85,0"Name="Submit"VerticalAlignment="Top"
Grid.Column="1"h:HelpProvider.HelpString="Presssubmitbuttontosave.">Submit</Button>
</Grid>
</Window>

Now press F1 on NameField displays "Enter your name.", and F1 on the Submit button displays "Press submit button to save.".

Finally, note that you can also do more exciting things in the help handler, like load a chm file with the System.Windows.Forms.Help class.

Finally, note that you can also do more exciting things in the help handler, like load a chm file with the System.Windows.Forms.Help class. You can also load the chm or html file from the xaml by specifying the path of the file.

h:HelpProvider.HelpString="MyHelp.chm"

staticprivatevoidExecuted(objectsender,ExecutedRoutedEventArgse)
{
System.Windows.Forms.Help.ShowHelp(null,@"MyHelp.chm");
}

Now the class will look like this.

staticclassHelpProvider
{
publicstaticreadonlyDependencyPropertyHelpStringProperty=
DependencyProperty.RegisterAttached("HelpString",typeof(string),typeof(HelpProvider));
staticHelpProvider()
{
CommandManager.RegisterClassCommandBinding(typeof(FrameworkElement),new
CommandBinding(ApplicationCommands.Help,newExecutedRoutedEventHandler
(Executed),newCanExecuteRoutedEventHandler(CanExecute)));
}
publicstaticvoidSetHelpString(DependencyObjectobj,stringvalue)
{
obj.SetValue(HelpStringProperty,value);
}
staticprivatevoidCanExecute(objectsender,CanExecuteRoutedEventArgse)
{
FrameworkElementsenderElement=senderasFrameworkElement;
if(HelpProvider.GetHelpString(senderElement)!=null)
e.CanExecute=true;
}
publicstaticstringGetHelpString(DependencyObjectobj)
{
return(string)obj.GetValue(HelpStringProperty);
}
staticprivatevoidExecuted(objectsender,ExecutedRoutedEventArgse)
{
Help.ShowHelp(null,HelpProvider.GetHelpString(senderasFrameworkElement));
}
}

I hope this post made life a little easier.
  • Edited byNiraj Singh Thursday, September 04, 2008 12:20 PMformatting was not proper
  •  
Niraj Singh
This is good and all, but you could have mentioned that this is a copy-paste post from Mike Hillberg
Dependency Visualizer - http://www.codeplex.com/dependencyvisualizer
Simon Dahlbacka
We've cribbed this code in our application and it works fine under Mozilla Firefox. Hit F1 and the desired page of the help file appears in a new window.

However, when we run under Internet Explorer, something odd happens. Sure, our context-sensitive help appears as it ought, BUT so does the Internet Explorer's help file. Don't want this. Seems that the F1-generated help gets handled by Internet Explorer before our application gets the event and displays its own help window.

Setting e.Handled = true in the delegate I registered doesn't help because (i think) Internet Explorer has gotten in line ahead of us.
StevePoling

You can use google to search for other answers

Custom Search

More Threads

• FontCacheFullException stutters my application
• How FlowDocumentReader does HTML render ? building an rss reader
• Unauthorised Acces
• How can I have nested data templates?
• Restricting the Width of an item in a ListView ItemTemplate
• How to auto jump to the next control in a canvas ?
• Binding to a non-dependency property
• BeginInit - EndInit
• Help with creating a dynamic style
• PhotoShop Blend Pixel Shader