我想在按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>
答案 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()
方法...但这种方法无效。