2009-11-18 3 views
0

У меня есть UserControl, который содержит текстовое поле. Я хочу, чтобы клавиатура фокусировалась на этом текстовом поле программно, когда пользователь нажимает кнопку. Я пробовал:Как настроить клавиатурный фокус на текстовое поле внутри UserControl программно?

private void Button_Click(object sender,EventArgs e) 
{ 
    Keyboard.Focus(MyUserControl); 
} 

не повезло. Затем я выставил текстовое поле в UserControl, хотя свойство типа TextBox

private void Button_Click(object sender,EventArgs e) 
{ 
    Keyboard.Focus(MyUserControl.TextBox); 
} 

снова не повезло. Наконец, я сделал обработчик событий в UserControl для обработки события GotKeyboardFocus, вызвав метод Keyboard.Focus в текстовом поле внутри него.

Снова не повезло ?!

Как это сделать ??

EDIT: Проблема не связана с UserControls. Это проблема, когда вы пытаетесь передать фокус другому элементу UIElement в клике или MouseDownHandler. XAML en code ниже ниже расскажет свою историю: фокус действительно переходит в текстовое поле, но украден обратно в списке.

<Window x:Class="FocusSpike.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window1" Height="300" Width="300"> 
    <StackPanel> 
     <TextBox Name="FocusedTextBox" Height="30"> 
      <TextBox.Style> 
       <Style TargetType="TextBox"> 
        <Setter Property="Text" Value="I am unfocused..."/> 
        <Setter Property="Opacity" Value=".3"/> 
        <Style.Triggers> 
         <Trigger Property="IsKeyboardFocused" Value="True"> 
          <Trigger.EnterActions> 
           <BeginStoryboard> 
            <Storyboard AutoReverse="True"> 
             <DoubleAnimation Storyboard.TargetProperty="FontSize" To="20"/> 
            </Storyboard> 
           </BeginStoryboard> 
          </Trigger.EnterActions> 
          <Setter Property="Text" Value="I am focused!"/> 
          <Setter Property="Opacity" Value="1"/> 
         </Trigger> 
        </Style.Triggers> 
       </Style> 
      </TextBox.Style> 
     </TextBox> 
     <Button>Click to steal focus.</Button> 
     <ListBox> 
      <ListBoxItem GotFocus="Listbox_GotFocus"> 
       <Label MouseDown="ListBoxItem_MouseDown"> 
        Click to restore focus 
       </Label> 
      </ListBoxItem> 
     </ListBox> 
    </StackPanel> 
</Window> 

using System.Windows; 
using System.Windows.Input; 
namespace FocusSpike 
{ 
    public partial class Window1 : Window 
    { 
     public Window1() 
     { 
      InitializeComponent(); 
      FocusedTextBox.Focus(); 
     } 

     private void ListBoxItem_MouseDown(object sender, MouseButtonEventArgs e) 
     { 
      Keyboard.Focus(FocusedTextBox);//This does not work, remove it! 
     } 

     private void Listbox_GotFocus(object sender, RoutedEventArgs e) 
     { 
      //Keyboard.Focus(FocusedTextBox);//uncomment to restore focus! 
     } 
    } 
} 

ответ

3
MyUserControl.FindControl("TextBox1").Focus(); 

В противном случае ...

(TextBox)(MyUserControl.FindControl("TextBox1")).Focus(); 
+0

или MyUserControl.TextBox.Focus() – Zenuka

+0

Да, просто это иногда их не видно ... – tsilb

+0

Спасибо за ответ. Это не работает, хотя ;-) Я начинаю подозревать, что фокус установлен на текстовое поле, но сразу же украден из него. Я буду исследовать дальше. – Dabblernl

6

Вы можете получить свой .Focus() вызов придерживаться с помощью Dispatcher.BeginInvoke задержать фактический Focus() вызова, пока обработчик Click или MouseDown события не завершен, и код вызова завершил работу.

Вот как это сделать:

private void ListBoxItem_MouseDown(object sender, MouseButtonEventArgs e) 
{ 
    //Keyboard.Focus(FocusedTextBox); // May be necessary to uncomment this in some scenarios 

    Dispatcher.BeginInvoke(DispatcherPriority.Input, new Action(() => 
    { 
    Keyboard.Focus(FocusedTextBox); 
    }); 
} 

Вот последовательность событий:

  1. WPF вызывает обработчик MouseDown
  2. Ваш обработчик MouseDown просит диспетчера WPF вызвать его обратно когда все вызовы DispatcherPriority.Input (и выше) завершены
  3. Ваш обработчик MouseDown возвращается, а код вызова завершает обработку
  4. Обработаны любые другие события ввода в очереди
  5. Ваше действие вызывается, а ваш код вызывает Keyboard.Focus(FocusedTextBox) для установки фокуса.

Ключевым моментом здесь является то, что KeyboardFocus.Focus() не не вызывается, пока обработчик вернулся и WPF завершил все в ожидании обработки ввода.

Возможно, сам вызов может вызвать запуск ListBox, чтобы украсть фокус у вас. Я этого не проверял. Если это так, решение должно было бы вызвать его дважды: один раз из обработчика MouseDown и снова из Action, запланированного обработчиком MouseDown. Поэтому, если он не работает с первой строкой, прокомментированной, раскомментируйте ее и повторите попытку.

+0

Я не понимаю: это асинхронный вызов, и даже если он начинается ПОСЛЕ того, как метод, который вызывает его, завершился. Вы имеете в виду под «задержкой» время покупки и надеемся получить правильное время (получение разных результатов между компьютерами на основе их скорости), или вы имеете в виду, что метод BeginInvoked будет надежно не выполняться до завершения метода вызова? Это было бы странно: что, если я в злостном настроении поставлю нить. Сразу после BeginInvoke? – Dabblernl

+0

Это не связано с синхронизацией или скоростью компьютера. Вызов BeginInvoke, который я дал, выполняет вызов KeyBoard.Focus() в детерминированной последовательности. В частности, он выполняет его после: 1. Текущий вызов завершен, 2. Все вызовы выше DispatcherPriority.Input завершены и 2. Все * в настоящее время запланированные * вызовы в DispatcherPriority.Input завершены. В то время, когда это условие выполняется (когда бы оно ни было), ваш код KeyboardFocus (FocusedTextBox) будет выполнен. –

+0

'BeginInvoke' действительно не будет выполняться до тех пор, пока метод вызова не завершится. Если вы поместите 'Thread.Sleep()' сразу после 'BeginInvoke', фокус не будет изменяться до конца интервала ожидания. Конечно, 'Thread.Sleep()' также блокирует остальную часть пользовательского интерфейса. –

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