我有一个文本框,我有这个:
<KeyBinding Command="{Binding MyCommand}" Key="Tab"/>
问题是它吞下了标签而没有标签到下一个控件。 如何捕获文本框的Tab并仍然将Tab键保留到Tab键顺序中的下一个控件? 编辑:我也使用MVVM和MyCommand在ViewModel代码中,所以我需要重新抛出Tab。
答案 0 :(得分:0)
我无法找到一种方法将焦点设置为控件,因为您的问题是纯XAML解决方案 我选择创建一个attacted属性,然后通过绑定将焦点设置为与ViewModel中与KeyBinding关联的Command中的下一个控件。
以下是视图:
<Window x:Class="WarpTab.Views.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c="clr-namespace:WarpTab.Commands"
xmlns:Views="clr-namespace:WarpTab.Views"
xmlns:local="clr-namespace:WarpTab.ViewModels"
Title="Main Window" Height="400" Width="800">
<Window.Resources>
<c:CommandReference x:Key="MyCommandReference" Command="{Binding MyCommand}" />
</Window.Resources>
<DockPanel>
<ScrollViewer>
<WrapPanel >
<TextBox Text="First text value" >
<TextBox.InputBindings>
<KeyBinding Command="{StaticResource MyCommandReference}" Key="Tab"/>
</TextBox.InputBindings>
</TextBox>
<TextBox Text="Next text value" local:FocusExtension.IsFocused="{Binding FocusControl}" />
<Button Content="My Button" />
</WrapPanel>
</ScrollViewer>
</DockPanel>
</Window>
这是ViewModel:
using System.Windows.Input;
using WarpTab.Commands;
namespace WarpTab.ViewModels
{
public class MainViewModel : ViewModelBase
{
public ICommand MyCommand { get; set; }
public MainViewModel()
{
MyCommand = new DelegateCommand<object>(OnMyCommand, CanMyCommand);
}
private void OnMyCommand(object obj)
{
FocusControl = true;
// process command here
// reset to allow tab to continue to work
FocusControl = false;
return;
}
private bool CanMyCommand(object obj)
{
return true;
}
private bool _focusControl = false;
public bool FocusControl
{
get
{
return _focusControl;
}
set
{
_focusControl = value;
OnPropertyChanged("FocusControl");
}
}
}
}
以下是我在以下answer中找到的附加属性的代码。
using System.Windows;
namespace WarpTab.ViewModels
{
public static class FocusExtension
{
public static bool GetIsFocused(DependencyObject obj)
{
return (bool)obj.GetValue(IsFocusedProperty);
}
public static void SetIsFocused(DependencyObject obj, bool value)
{
obj.SetValue(IsFocusedProperty, value);
}
public static readonly DependencyProperty IsFocusedProperty =
DependencyProperty.RegisterAttached(
"IsFocused", typeof(bool), typeof(FocusExtension),
new UIPropertyMetadata(false, OnIsFocusedPropertyChanged));
private static void OnIsFocusedPropertyChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
var uie = (UIElement)d;
if ((bool)e.NewValue)
{
uie.Focus(); // Don't care about false values.
}
}
}
}
答案 1 :(得分:0)
为什么不在命令处理程序中使用此代码?
private void MyCommandHandler(){
// Do command's work here
TraversalRequest request = new TraversalRequest(FocusNavigationDirection.Next);
request.Wrapped = true;
control.MoveFocus(request);
}
这基本上就是'Tab'的作用,所以如果你这样做,你就会很高兴。 (当然,如果你有一个带有Shift-Tab的命令,则反转方向。
我实际上把它包装成一个像这样的扩展方法......
public static class NavigationHelpers{
public static void MoveFocus(this FrameworkElement control, FocusNavigationDirection direction = FocusNavigationDirection.Next, bool wrap = true) {
TraversalRequest request = new TraversalRequest(direction);
request.Wrapped = wrap;
control.MoveFocus(request);
}
}
...意味着先前的代码变得更加简单,就像这样......
private void MyCommandHandler(){
// Do command's work here
Control.MoveFocus();
}
...如果您不知道当前关注的控件是什么,您可以这样做......
(Keyboard.FocusedElement as FrameworkElement).MoveFocus();
希望这有帮助!如果是这样,非常感谢您投票给我或将其标记为已接受!
答案 2 :(得分:0)
遇到了同样的问题,遇到了这个问题,花了我一段时间才找到最佳答案。参考:Use EventTrigger on a specific key 定义此类:
using System; using System.Windows.Input; using System.Windows.Interactivity;
public class KeyDownEventTrigger : EventTrigger
{
public KeyDownEventTrigger() : base("KeyDown")
{
}
protected override void OnEvent(EventArgs eventArgs)
{
var e = eventArgs as KeyEventArgs;
if (e != null && e.Key == Key.Tab)
{
this.InvokeActions(eventArgs);
}
}
}
文本框的xaml:
<TextBox x:Name="txtZip"
Text="{Binding Zip, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<TextBox.InputBindings>
<KeyBinding Key="Enter" Command="{Binding ZipLookup.GetAddressByZipKeyCommand}" CommandParameter="{Binding ElementName=txtZip, Path=Text}" />
</TextBox.InputBindings>
<i:Interaction.Triggers>
<iCustom:KeyDownEventTrigger EventName="KeyDown">
<i:InvokeCommandAction Command="{Binding ZipLookup.GetAddressByZipKeyCommand}" CommandParameter="{Binding ElementName=txtZip, Path=Text}" />
</iCustom:KeyDownEventTrigger>
</i:Interaction.Triggers>
</TextBox>
在窗口或用户控件的根标记中,包括以下属性:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:iCustom="clr-namespace:[NAMESPACE FOR CUSTOM KEY DOWN CLASS]"
答案 3 :(得分:0)
这很容易实现,只是不要为此使用KeyBinding。处理您的TextBox的OnKeyDown事件:
class TestClass {
init() {
let node = SKSpriteNode(color:.red,size:CGSize(width:100,height:100))
let sequence = SKAction.sequence([.fireFromEnemy, .wait(forDuration: 10), .removeFromParent()])
node.run(sequence)
}
}
extension SKAction {
static let fireFromEnemy = SKAction.customAction(withDuration: 0.3) { node, elapsedTime in
// Do stuff here like:
node.alpha = 0.5
node.zRotation = .pi
}
}
然后在代码背后,每当按下Tab键时执行命令。与KeyBinding不同,它不会吞下TextInput事件,因此它应该可以工作。
<TextBox KeyDown="UIElement_OnKeyDown" ...