Интеграция справки в приложении WPF

Каковы возможные подходы к интеграции локальной (а не он-лайн) помощи в приложении WPF? Это было бы скорее как руководство, но я хотел бы каким-то образом интегрировать его.

EDIT: только что нашел http://wordtoxaml.codeplex.com, я попробую это. Он преобразует документ word в xaml, который я могу отобразить в WPF.

EDIT 2: Я нашел рабочее решение: напишите руководство в слове, сохраните его как 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

Ответ 1

Мы используем RoboHelp и генерируем файл chm, иногда называемый файлом справки HTML. Класс .NET Framework Help имеет метод ShowHelp, который вы вызываете, передавая файл chm и тему, которую хотите отобразить. Вы можете сказать, что он отображает заголовок темы, идентификатор и т.д. Мы показываем, используя заголовок темы, чтобы вызов выглядел следующим образом:

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

Затем вы можете создать класс под названием 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 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 .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 the 
    /// source of the call.</remarks>
    private static void ShowHelpExecuted(object sender, ExecutedRoutedEventArgs e)
    {
        ShowHelpTopic(HelpProvider.GetHelpTopic(sender as FrameworkElement));
    }

    #endregion Methods
}

С помощью этого кода вы можете вызвать свою помощь из кода следующим образом:

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

Что еще приятнее, теперь вы можете приложить помощь к любому элементу 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"/>
    ...

Теперь, когда пользователь нажимает F1 на окна или какой-либо элемент, они получат контекстно-зависимую помощь.

Ответ 2

У вас посмотрите этот пост, это то, что вы ищете?

Существует много видов помощи: ручной, контекстно-зависимый,...

Ответ 3

У меня была аналогичная потребность, за исключением того, что мне нужно было только подключить ключ F1 к нашему существующему коду справки.

В итоге я собрал около 5 разных страниц StackOverflow, поэтому я помещаю их здесь, если у кого-то есть аналогичная потребность.

В моем MainWindow.xaml я добавил KeyBinding в inputBindings для подключения F1 к ICommand:

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

Затем в моем MainWindowViewModel.cs я добавил эту ICommand, которая вызывает мой существующий код справки.

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

Я надеюсь, что это поможет любому, у кого есть подобная проблема, и я не думал, что это того стоит. Приветствия.