从父视图中聚焦textBox元素

时间:2015-04-13 15:34:41

标签: c# wpf

我想在按ctrl + f时聚焦文本框搜索元素,但此文本框位于mainWindow的contentControl中。因此,当在ContentControl中聚焦时,我可以从子视图的处理程序中聚焦它。但是当焦点在主窗口时我应该以某种方式从父窗口聚焦它。我怎么能这样做?

MainWindow

<Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary>
                    <DataTemplate DataType="{x:Type mainWindowViewModel:SummaryViewModel}">
                        <mainWindow:SummaryView />
                    </DataTemplate>
 </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>
 <ContentControl x:Name="InnerControl" Content="{Binding Path=ContentViewModel}" />

Child view:

<UserControl x:Class="View.Settings.MainSettingsView"

             Name="MainSettings"
             PreviewKeyDown="MainSettingsView_OnPreviewKeyDown">

                <TextBox Name="SearchBox"
                         Style="{StaticResource TextBoxTopNavigationStyle}"
                         TextChanged="TextBoxBase_OnTextChanged" />

             </UserControl>

2 个答案:

答案 0 :(得分:0)

为您的案例使用InputBinding。

在mainwindow.xaml中添加以下代码。

<Window.InputBindings>
  <KeyBinding Command="ApplicationCommands.Open"
              Gesture="CTRL+F" />
</Window.InputBindings>

在keybindings命令事件中显示子usercontrol。

了解更多refer MSDN

编辑1:

这里我添加了一个示例,在按CTRL + F时显示文本框,并再次按CTRL + F隐藏。

<强> Prerequistes:

正如您所提到的,您没有使用Galasoft而只使用MVVM模式。因此,如果您没有RelayCommand.cs,请将其添加到您的项目中。

RelayCommand.cs

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace SO // Note: Change namespace
{
    public class RelayCommand : ICommand
    {
        #region Fields

        readonly Action<object> _execute;
        readonly Predicate<object> _canExecute;

        #endregion // Fields

        #region Constructors

        public RelayCommand(Action<object> execute)
            : this(execute, null)
        {
        }

        public RelayCommand(Action<object> execute, Predicate<object> canExecute)
        {
            if (execute == null)
                throw new ArgumentNullException("execute");

            _execute = execute;
            _canExecute = canExecute;
        }
        #endregion // Constructors

        #region ICommand Members

        [DebuggerStepThrough]
        public bool CanExecute(object parameter)
        {
            return _canExecute == null ? true : _canExecute(parameter);
        }

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        public void Execute(object parameter)
        {
            _execute(parameter);
        }

        #endregion // ICommand Members
    }
}

<强> MainWindow.xaml

<Window x:Class="SO.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
xmlns:PopUpFind ="clr-namespace:SO"
        Title="MainWindow" Height="350" Width="525">
    <Window.InputBindings>
        <KeyBinding Command="{Binding ShowFindControl}"
              Gesture="CTRL+F" />
    </Window.InputBindings>
    <Grid>
        <PopUpFind:PopUpUC Visibility="{Binding PopUpFindVisibility}" />
    </Grid>
</Window>

<强> MainWindow.xaml.cs

using System.Windows;

namespace SO
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new MainModel();
        }   

    }
}

<强> MainModel.cs

using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Input;

namespace SO
{
    class MainModel : INotifyPropertyChanged
    {
        public ICommand ShowFindControl
        {
            get;
            set;
        }
        private Visibility _PopUpFindVisibility = Visibility.Hidden;
        public Visibility PopUpFindVisibility
        {
            get { return _PopUpFindVisibility; }
            set
            {
                _PopUpFindVisibility = value;
                OnPropertyChanged("PopUpFindVisibility");
            }
        }
        public MainModel()
        {
            ShowFindControl = new RelayCommand(MakeVisible);
        }

        private void MakeVisible(Object obj)
        {
            PopUpFindVisibility = (PopUpFindVisibility == Visibility.Hidden) ? Visibility.Visible : Visibility.Hidden;
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

答案 1 :(得分:0)

一种更简单的方法,只在UserControl中工作,而不是严格的MVVM,可能是创建绑定到父窗口的KeyTrigger(无论焦点如何都将捕获关键事件)。您可以使用RelativeSource FindAncestor绑定实现此目的。这将搜索可视树,直到遇到您指定类型的控件。在这种情况下,我们正在寻找主窗口控件。

<UserControl 
    x:Class="View.Settings.MainSettingsView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
    Name="MainSettings">

    <i:Interaction.Triggers>
        <ei:KeyTrigger Key="F" Modifiers="Ctrl" SourceObject="{Binding Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}">
            <ei:CallMethodAction TargetObject="{Binding ElementName=MainSettings, Mode=OneWay}" MethodName="SetTextboxFocus"/>
        </ei:KeyTrigger>
    </i:Interaction.Triggers>

    <TextBox Name="SearchBox"
    Style="{StaticResource TextBoxTopNavigationStyle}"
    TextChanged="TextBoxBase_OnTextChanged" />

</UserControl>

KeyTrigger导致CallMethodAction在usercontrol上调用SetTextboxFocus()方法。所以你只需要将这个方法添加到你的usercontrol代码后面:

public void SetTextboxFocus()
{
    SearchBox.Focus();
}

希望将KeyTrigger绑定到父窗口而不是用户控件,可以解决您的问题。

注意:我最初尝试使用CallMethodAction直接调用SearchBox的Focus()方法...但这种方法无效。