在 WPF 应用程序中集成帮助

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5116465/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 22:37:30  来源:igfitidea点击:

Integrating help in a WPF application

wpf

提问by L-Four

what are the possible approaches to integrate local (so not on-line) help in a WPF application? It would be more like a manual, but I would like to integrate it in some way.

在 WPF 应用程序中集成本地(所以不是在线)帮助的可能方法是什么?它更像是一本手册,但我想以某种方式整合它。

EDIT: just found http://wordtoxaml.codeplex.com, I will try that one. It converts word document into xaml, which I can display in WPF.

编辑:刚刚找到http://wordtoxaml.codeplex.com,我会尝试那个。它将word文档转换为xaml,我可以在WPF中显示。

EDIT 2: I found a working solution: write manual in word, save as XPS, and display it using https://web.archive.org/web/20111116005415/http://www.umutluoglu.com/english/post/2008/12/20/Showing-XPS-Documents-with-DocumentViewer-Control-in-WPF.aspx

编辑 2:我找到了一个可行的解决方案:用 Word 编写手册,另存为 XPS,然后使用https://web.archive.org/web/20111116005415/http://www.umutluoglu.com/english/post/显示它2008/12/20/Showing-XPS-Documents-with-DocumentViewer-Control-in-WPF.aspx

回答by Nigel Shaw

We use RoboHelp and generate a chm file, sometimes referred to as an HTML Help file. The .NET Framework's Helpclass has a method ShowHelpthat you call, passing the chm file and the topic you want to display. You can tell it to display by topic title, by ID etc. We display using the topic title so the call looks like this:

我们使用 RoboHelp 并生成一个 chm 文件,有时也称为 HTML 帮助文件。.NET Framework 的Help类有一个ShowHelp您调用的方法,传递 chm 文件和您要显示的主题。您可以告诉它按主题标题、ID 等显示。我们使用主题标题显示,因此调用如下所示:

System.Windows.Forms.Help.ShowHelp(null, "Help/ExiaProcess.chm", HelpNavigator.Topic, helpTopic);

Next you can create a class called HelpProvider that creates an attached property called HelpTopic. This allows you to attach a HelpTopic property to any FrameworkElement. The class also uses the static constructor to hook the built-in F1 help command to command handlers that retrieve the attached property from the source and open the help.

接下来,您可以创建一个名为 HelpProvider 的类,该类创建一个名为 HelpTopic 的附加属性。这允许您将 HelpTopic 属性附加到任何 FrameworkElement。该类还使用静态构造函数将内置 F1 帮助命令挂接到命令处理程序,这些处理程序从源代码检索附加属性并打开帮助。

using System.Windows;
using System.Windows.Forms;
using System.Windows.Input;

/// <summary>
/// Provider class for online help.  
/// </summary>
public class HelpProvider
{
    #region Fields

    /// <summary>
    /// Help topic dependency property. 
    /// </summary>
    /// <remarks>This property can be attached to an object such as a form or a textbox, and 
    /// can be retrieved when the user presses F1 and used to display context sensitive help.</remarks>
    public static readonly DependencyProperty HelpTopicProperty = 
        DependencyProperty.RegisterAttached("HelpString", typeof(string), typeof(HelpProvider));

    #endregion Fields

    #region Constructors

    /// <summary>
    /// Static constructor that adds a command binding to Application.Help, binding it to 
    /// the CanExecute and Executed methods of this class. 
    /// </summary>
    /// <remarks>With this in place, when the user presses F1 our help will be invoked.</remarks>
    static HelpProvider()
    {
        CommandManager.RegisterClassCommandBinding(
            typeof(FrameworkElement),
            new CommandBinding(
                ApplicationCommands.Help,
                new ExecutedRoutedEventHandler(ShowHelpExecuted),
                new CanExecuteRoutedEventHandler(ShowHelpCanExecute)));
    }

    #endregion Constructors

    #region Methods

    /// <summary>
    /// Getter for <see cref="HelpTopicProperty"/>. Get a help topic that's attached to an object. 
    /// </summary>
    /// <param name="obj">The object that the help topic is attached to.</param>
    /// <returns>The help topic.</returns>
    public static string GetHelpTopic(DependencyObject obj)
    {
        return (string)obj.GetValue(HelpTopicProperty);
    }

    /// <summary>
    /// Setter for <see cref="HelpTopicProperty"/>. Attach a help topic value to an object. 
    /// </summary>
    /// <param name="obj">The object to which to attach the help topic.</param>
    /// <param name="value">The value of the help topic.</param>
    public static void SetHelpTopic(DependencyObject obj, string value)
    {
        obj.SetValue(HelpTopicProperty, value);
    }

    /// <summary>
    /// Show help table of contents. 
    /// </summary>
    public static void ShowHelpTableOfContents()
    {
        System.Windows.Forms.Help.ShowHelp(null, "Help/ExiaProcess.chm", HelpNavigator.TableOfContents);
    }

    /// <summary>
    /// Show a help topic in the online CHM style help. 
    /// </summary>
    /// <param name="helpTopic">The help topic to show. This must match exactly with the name 
    /// of one of the help topic's .htm files, without the .htm extention and with spaces instead of underscores
    /// in the name. For instance, to display the help topic "This_is_my_topic.htm", pass the string "This is my topic".</param>
    /// <remarks>You can also pass in the help topic with the underscore replacement already done. You can also 
    /// add the .htm extension. 
    /// Certain characters other than spaces are replaced by underscores in RoboHelp help topic names. 
    /// This method does not yet account for all those replacements, so if you really need to find a help topic
    /// with one or more of those characters, do the underscore replacement before passing the topic.</remarks>
    public static void ShowHelpTopic(string helpTopic)
    {
        // Strip off trailing period.
        if (helpTopic.IndexOf(".") == helpTopic.Length - 1)
            helpTopic = helpTopic.Substring(0, helpTopic.Length - 1);

        helpTopic = helpTopic.Replace(" ", "_").Replace("\", "_").Replace("/", "_").Replace(":", "_").Replace("*", "_").Replace("?", "_").Replace("\"", "_").Replace(">", "_").Replace("<", "_").Replace("|", "_") + (helpTopic.IndexOf(".htm") == -1 ? ".htm" : "");
        System.Windows.Forms.Help.ShowHelp(null, "Help/ExiaProcess.chm", HelpNavigator.Topic, helpTopic);
    }

    /// <summary>
    /// Whether the F1 help command can execute. 
    /// </summary>
    private static void ShowHelpCanExecute(object sender, CanExecuteRoutedEventArgs e)
    {
        FrameworkElement senderElement = sender as FrameworkElement;

        if (HelpProvider.GetHelpTopic(senderElement) != null)
            e.CanExecute = true;
    }

    /// <summary>
    /// Execute the F1 help command. 
    /// </summary>
    /// <remarks>Calls ShowHelpTopic to show the help topic attached to the framework element that's the 
    /// source of the call.</remarks>
    private static void ShowHelpExecuted(object sender, ExecutedRoutedEventArgs e)
    {
        ShowHelpTopic(HelpProvider.GetHelpTopic(sender as FrameworkElement));
    }

    #endregion Methods
}

With that in place, you can call your help from code like this:

有了这个,你可以从这样的代码中调用你的帮助:

private void HelpButton_Click(object sender, RoutedEventArgs e)
{
    Help.HelpProvider.ShowHelpTopic("License Key Dialog");
}

What's even nicer, now you can attach help to any FrameworkElement in your UI like this,

更好的是,现在您可以像这样将帮助附加到 UI 中的任何 FrameworkElement,

<Window name="MainWin"
    ...
    ...
    xmlns:help="clr-namespace:ExiaProcess.UI.Help"
    ...
    ...
    help:HelpProvider.HelpTopic="Welcome to YourApp" />      
    ...
    ...
    <TextBox help:HelpProvider.HelpTopic="Bug Title" />
    ...
    ...
    <ComboBox help:HelpProvider.HelpTopic="User Drop Down"/>
    ...

Now when the user presses F1 on the windows or any element, they'll get context-sensitive help.

现在,当用户在窗口或任何元素上按 F1 时,他们将获得上下文相关的帮助。

回答by CodeChops

I had a similar need except I only needed to wire up the F1 key to our existing Help code.

我有类似的需求,只是我只需要将 F1 键连接到我们现有的帮助代码。

I ended up pulling a mix of about 5 different StackOverflow pages so I'm putting it here in case someone else has a similar need.

我最终混合了大约 5 个不同的 StackOverflow 页面,所以我把它放在这里以防其他人有类似的需求。

In my MainWindow.xaml I added a KeyBinding in inputBindings to wire the F1 to an ICommand:

在我的 MainWindow.xaml 中,我在 inputBindings 中添加了一个 KeyBinding 以将 F1 连接到 ICommand:

<Window.InputBindings>
    (other bindings here...)
    <KeyBinding Key="F1" Command="{Binding Path=ShowHelpCommand}"/>
</Window.InputBindings>

Then in my MainWindowViewModel.cs I added this ICommand which calls my existing Help code.

然后在我的 MainWindowViewModel.cs 中,我添加了这个调用我现有帮助代码的 ICommand。

    private ICommand _showHelpCommand;
    public ICommand ShowHelpCommand
    {
        get
        {
            return _showHelpCommand ??
                   (_showHelpCommand = new RelayCommand(p => DisplayCREHelp(), p => true));
        }
    }

I hope this helps anyone with a similar issue and I didn't think it was worth it's own thread. Cheers.

我希望这可以帮助任何有类似问题的人,我认为这不值得拥有自己的线程。干杯。