【问题标题】:Integrating Context-Sensitive help in WPF application following MVVM在 MVVM 之后在 WPF 应用程序中集成上下文相关帮助
【发布时间】:2013-06-10 10:44:34
【问题描述】:

我正在尝试为遵循 MVVM 模式的 wpf 应用程序实现帮助功能。我有我的帮助文件,其中包含根据应用程序的许多页面。现在我需要将它集成到我的应用程序中。

这是我的要求:

  1. 按 F1 可打开帮助文件中的特定页面,具体取决于视图模型。为此,我想,我需要将 F1 命令绑定到我的视图模型。我们如何在视图中绑定键?
  2. 在文本字段上按 F1 可打开该文本字段的帮助。我认为这与要求 1 相同。但这里的问题是我如何知道选择了某个文本字段、按钮或单选按钮?

【问题讨论】:

    标签: c# wpf mvvm context-sensitive-help


    【解决方案1】:
    1. 侦听视图(或视图的基类)中的键并在 DataContext 上的 HelpCommand 上调用 execute。

    2. the control that has focus(或其 id 或标签...)作为参数传递给 HelpCommand。

    Alternative way to find the focussed control 使用 FocusManager

    这是一个例子:

    ContextHelp C#:

    public static class ContextHelp
    {
        public static readonly DependencyProperty KeywordProperty =
            DependencyProperty.RegisterAttached(
                "Keyword",
                typeof(string),
                typeof(ContextHelp));
    
        public static void SetKeyword(UIElement target, string value)
        {
            target.SetValue(KeywordProperty, value);
        }
    
        public static string GetKeyword(UIElement target)
        {
            return (string)target.GetValue(KeywordProperty);
        }
    }
    

    ViewBase:

    public abstract class ViewBase : UserControl
    {
        public ViewBase()
        {
            this.KeyUp += ViewBase_KeyUp;
            this.GotFocus += ViewBase_GotFocus;
        }
    
        void ViewBase_GotFocus(object sender, RoutedEventArgs e)
        {
            FocusManager.SetIsFocusScope(this, true);
        }
    
        void ViewBase_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
        {
            if (e.Key == Key.F1)
            {
                var viewModel = this.DataContext as ViewModelBase;
                if (viewModel != null)
                {
                    var helpTopic = "Index";
                    var focusedElement = 
                        FocusManager.GetFocusedElement(this) as FrameworkElement;
                    if (focusedElement != null)
                    {
                        var keyword = ContextHelp.GetKeyword(focusedElement);
                        if (!String.IsNullOrWhiteSpace(keyword))
                        {
                            helpTopic = keyword;
                        }
                    }
                    viewModel.HelpCommand.Execute(helpTopic);
                }
            }
        }
    }
    

    ViewModelBase:

    public abstract class ViewModelBase: INotifyPropertyChanged
    {
        public ICommand HelpCommand { get; set; }
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        protected void OnPropertyChanged([CallerMemberName] string propertyName="")
        {
            var p = PropertyChanged;
            if (p != null)
            {
                p(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
    

    AViewModel:

    class AViewModel : ViewModelBase
    {
        public AViewModel()
        {
            HelpCommand = new RelayCommand(HelpCommandExecuted, (p)=>true);
        }
    
        private void HelpCommandExecuted(object parameter)
        {
            var topic = parameter as string;
            if (!String.IsNullOrWhiteSpace(topic))
            {
                HelpText = String.Format("Information on the interesting topic: {0}.", topic);
            }
        }
    
        private string _helpText;
    
        public string HelpText
        {
            get { return _helpText; }
            private set
            {
                if (_helpText != value)
                {
                    _helpText = value;
                    OnPropertyChanged();
                }
            }
        }
    }
    

    AView C#:

    public partial class AView : ViewBase
    {
        public AView()
        {
            InitializeComponent();
        }
    }
    

    查看 XAML:

    <local:ViewBase x:Class="WpfApplication2.AView"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 xmlns:local="clr-namespace:WpfApplication2"
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300">
        <Grid>
            <Label Content="{Binding HelpText}" Margin="10,254,10,0" VerticalAlignment="Top" Height="36"/>
            <Button local:ContextHelp.Keyword="Button Info" Content="Button" HorizontalAlignment="Left" Margin="192,32,0,0" VerticalAlignment="Top" Width="75"/>
            <TextBox local:ContextHelp.Keyword="TextBox Info" HorizontalAlignment="Left" Height="23" Margin="29,32,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120"/>
            <CheckBox local:ContextHelp.Keyword="CheckBox Info" Content="CheckBox" HorizontalAlignment="Left" Margin="29,80,0,0" VerticalAlignment="Top"/>
            <ComboBox local:ContextHelp.Keyword="ComboBox Info" HorizontalAlignment="Left" Margin="138,80,0,0" VerticalAlignment="Top" Width="120"/>
        </Grid>
    </local:ViewBase>
    

    主窗口 XAML:

    <Window
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:WpfApplication2" x:Class="WpfApplication2.MainWindow"
            Title="MainWindow" Height="700" Width="500">
        <Grid x:Name="ViewPlaceholder">
        </Grid>
    </Window>
    

    主窗口 C#:

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
    
            var view = new AView();
            var viewModel = new AViewModel();
            view.DataContext = viewModel;
            ViewPlaceholder.Children.Clear();
            ViewPlaceholder.Children.Add(view);
        }
    }
    

    【讨论】:

    • 我通过创建附加属性来注入帮助关键字进行了更改。所以不再劫持 Tag 属性。添加了 ContextHelp 类并更改了 ViewBase 和 AView.Xaml
    • 我试过你的第一个版本。我启动应用程序,按 F-1,没有任何反应。之后,我单击一些文本框或列表视图,然后按 F-1 帮助文件打开。因此,当我启动应用程序并且不选择任何控件时,ViewBase_KeyUp 不会启动。这背后的原因是什么。
    • 您需要一个专注的视图才能使其工作。因此,您可以在应用程序加载时从代码中设置焦点。
    猜你喜欢
    • 2013-12-31
    • 2011-07-04
    • 1970-01-01
    • 2013-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-21
    • 2020-12-18
    相关资源
    最近更新 更多