2010-08-10 6 views
5

У меня есть текстовое поле, где у меня есть это: <KeyBinding Command="{Binding MyCommand}" Key="Tab"/>WPF: KeyBinding для Tab, глотает Tab и не передать его

Проблемы она проглатывает Tab и не вкладки к следующему элементу управления , Как я могу уловить вкладку для текстового поля и сохранить привязку к следующему элементу управления в порядке вкладок? Редактирование: Я также использую MVVM, а MyCommand находится в коде ViewModel, поэтому мне нужно повторно нажать Tab.

+1

Возможно, событие 'LostFocus' больше подходит для ваших целей? (Я по-прежнему считаю ваш вопрос интересным, поэтому +1.) – Heinzi

+0

Я посмотрел в LostFocus, но с моим редактированием я использую MVVM, я бы не хотел вводить там код. – mike

+0

Я думаю больше о LostFocus, как я могу привязать команду к событию LostFocus? Я хочу, чтобы это не было сделано, не вставляя код в код xaml позади, только привязывая команду к моей модели ViewModel. – mike

ответ

0

Я не могу найти способ установить фокус на элемент управления, учитывая ваш вопрос как чисто решение XAML.
Я выбираю создать свойство attacted, а затем через привязку привязывает фокус к следующему элементу управления из команды, связанной с вашим KeyBinding в ViewModel.

Вот Вид:

<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. 
     } 
    } 
    } 
} 
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(); 

Надеюсь, это поможет! Если да, то очень ценим, если вы проголосуете за меня или отметьте его как принято!

+0

ViewModel не имеет никакого элемента FrameworkElement для перемещения фокуса. – Nick

Смежные вопросы