最近在看帮助文档实现部分,前面看了一下C#里面有个HelpProvider类用于实现帮助文档,但是后来发现WPF里面居然没有这个控件,甚是郁闷,所以就在网上找找,下面就是所有的相关网页,内容不多,主要就是以下两个例子:
第一个例子,只有一篇文章介绍,也没有看到别人转载:
http://blogs.windowsclient.net/bragi/archive/2008/04/08/html-help-from-within-wpf-applications.aspx
作者写了个dll,感觉功能并没有多少,但是dll工程中的类比较多,也挺大,所以没有仔细研究。
第二个例子,这个应该是最佳解决方案,有几个文章提到了,方法一样,只是侧重点稍有不同,结合起来可以看得更全面些,下面是找到:
1. http://blogs.msdn.com/mikehillberg/archive/2007/07/26/a-context-sensitive-help-provider-in-wpf.aspx
2. http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/3e947603-a883-4ada-9b30-55d365b83c33
3. http://www.codeproject.com/Articles/36117/Easy-help-with-WPF.aspx
经过研究,第1篇讲的比较详细,第2篇一般,第3篇应用范围广,包括了keyword。所以使用的话建议参考第3篇,看介绍的话参考第1篇。
但是在刚开始使用第3篇的代码时遇到了一些问题,还以为代码有问题,做了很大改动还是不行,编译有错,最后回过头来才发现了问题。
文章作者使用这样的xaml:
xmlns:help="clr-namespace:HelpProvider;assembly=HelpProvider"
help:Help.Filename="MyHelpfile.chm"
因为我的类HelpProvider并没有放在一个独立的工程里面,所以出现错误,而且开始还没有找到错误问题,还以为是静态类、或者Helpname没有定义等问题。
下面我把我测试过的代码贴在下面:
<Window x:Class="TestWPFHelp2.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300"
xmlns:h="clr-namespace:ContextSensitiveHelp"
h:HelpProvider.Filename="Help1.chm" h:HelpProvider.Keyword="button.html">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width='auto'/>
<ColumnDefinition Width='*'/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height='auto'/>
<RowDefinition Height='auto' />
</Grid.RowDefinitions>
<TextBlock Grid.Column='0' Grid.Row='0' >Name:</TextBlock>
<TextBlock Grid.Column='0' Grid.Row='1' >Address</TextBlock>
<TextBox Grid.Column='1' Grid.Row='0' Name='NameField' h:HelpProvider.Keyword="general.html"/>
<TextBox Grid.Column='1' Grid.Row='1' Name='AddressField' h:HelpProvider.Keyword="textbox.html"/>
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using ContextSensitiveHelp;
namespace TestWPFHelp2
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
}
}
namespace ContextSensitiveHelp
{
/// <summary>
/// This class provides the ability to easily attach Help functionality to Framework elements.
/// To use it, you need to add a reference to the HelpProvider in your XAML.
/// The FilenameProperty specifies the name of the help file, and the KeywordProperty specifies the keyword to be used with the search.
/// </summary>
/// <remarks>
/// The FilenameProperty can be at a higher level of the visual tree than the KeywordProperty, so you don't need to set the filename each time.
/// </remarks>
static class HelpProvider
{
static HelpProvider()
{
CommandManager.RegisterClassCommandBinding(typeof(FrameworkElement),
new CommandBinding(ApplicationCommands.Help,
new ExecutedRoutedEventHandler(Executed),
new CanExecuteRoutedEventHandler(CanExecute)));
}
#region Filename
/// <summary>
/// Filename Attached Dependency Property
/// </summary>
public static readonly DependencyProperty FilenameProperty =
DependencyProperty.RegisterAttached("Filename", typeof(string), typeof(HelpProvider));
/// <summary>
/// Gets the Filename property.
/// </summary>
public static string GetFilename(DependencyObject d)
{
return (string)d.GetValue(FilenameProperty);
}
/// <summary>
/// Sets the Filename property.
/// </summary>
public static void SetFilename(DependencyObject d, string value)
{
d.SetValue(FilenameProperty, value);
}
#endregion
#region Keyword
/// <summary>
/// Keyword Attached Dependency Property
/// </summary>
public static readonly DependencyProperty KeywordProperty =
DependencyProperty.RegisterAttached("Keyword", typeof(string), typeof(HelpProvider));
/// <summary>
/// Gets the Keyword property.
/// </summary>
public static string GetKeyword(DependencyObject d)
{
return (string)d.GetValue(KeywordProperty);
}
/// <summary>
/// Sets the Keyword property.
/// </summary>
public static void SetKeyword(DependencyObject d, string value)
{
d.SetValue(KeywordProperty, value);
}
#endregion
#region Event
private static void CanExecute(object sender, CanExecuteRoutedEventArgs args)
{
FrameworkElement el = sender as FrameworkElement;
if (el != null)
{
string fileName = FindFilename(el);
if (!string.IsNullOrEmpty(fileName))
args.CanExecute = true;
}
}
private static void Executed(object sender, ExecutedRoutedEventArgs args)
{
// Call ShowHelp.
DependencyObject parent = args.OriginalSource as DependencyObject;
string keyword = GetKeyword(parent);
if (!string.IsNullOrEmpty(keyword))
{
System.Windows.Forms.Help.ShowHelp(null, FindFilename(parent), keyword);
}
else
{
System.Windows.Forms.Help.ShowHelp(null, FindFilename(parent));
}
}
private static string FindFilename(DependencyObject sender)
{
if (sender != null)
{
string fileName = GetFilename(sender);
if (!string.IsNullOrEmpty(fileName))
return fileName;
return FindFilename(VisualTreeHelper.GetParent(sender));
}
return null;
}
#endregion
}
}
代码和.chm文件上传到了csdn资源,点击下载:Test WPF Help Project .rar。
(help1.chm文件在/bin/Debug/Help1.chm)
测试的时候,发现即使某个控件如TextBox没有定义Keyword,它所显示的帮助文档的Keyword是其他控件的,而不是父窗口的,所以我增加了一个函数:
private static string FindKeyword(DependencyObject sender)
{
if (sender != null)
{
string keyword = GetKeyword(sender);
if (!string.IsNullOrEmpty(keyword))
return keyword;
return FindKeyword(VisualTreeHelper.GetParent(sender));
}
return null;
}
并且修改了这个函数:
private static void Executed(object sender, ExecutedRoutedEventArgs args)
{
// Call ShowHelp.
DependencyObject parent = args.OriginalSource as DependencyObject;
string keyword = FindKeyword(parent);
string filename = FindFilename(parent);
if (!string.IsNullOrEmpty(keyword))
{
System.Windows.Forms.Help.ShowHelp(null, filename, keyword);
}
else
{
System.Windows.Forms.Help.ShowHelp(null, filename);
}
}
这样的话工作就比较正常了。
同时,使用了ShowHelpIndex去显示Index:
System.Windows.Forms.Help.ShowHelpIndex(null, FindFilename(parent));
Help::ShowHelp还有一些重载函数,大家可以根据自己需求进行更改,会有更好的效果。
具体查看msdn:http://msdn.microsoft.com/en-us/library/system.windows.forms.help.showhelp.aspx。