在样式触发器中为TextBox设置焦点

Han*_*ank 2 wpf xaml textbox focus popup

我有以下但触发器不起作用.它应该将光标放在TextBox准备输入中.

请有人指出我正确的方向.

<Popup Name="PopupGoto" Placement="Mouse" StaysOpen="False" 
       IsOpen="{Binding Path=GotoPopupIsOpen, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}">

    <Popup.Style>
        <Style TargetType="Popup">
            <Style.Triggers>
                <Trigger Property="IsOpen" Value="True">
                    <Setter Property="FocusManager.FocusedElement" Value="{Binding ElementName=GotoTextbox}" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </Popup.Style>

    <Border>
        <Grid>
            <TextBox x:Name="GotoTextbox" Text="{Binding GotoLineNumber}" />
            <Button Content="Goto" Command="{Binding GotoCommand}" />
        </Grid>
    </Border>
</Popup>
Run Code Online (Sandbox Code Playgroud)

Ana*_*aev 6

FocusManager.FocusedElement确立了元件的逻辑焦点:

确定此属性附加到的元素是否具有逻辑焦点.

这是什么意思?这意味着,在WPF中有两个与焦点相关的主要概念:键盘焦点和逻辑焦点[ MSDN].以下是一个例子:

<TextBox Name="GotoTextbox" 
         Text="TestText"
         Keyboard.GotKeyboardFocus="GotoTextbox_GotKeyboardFocus" 
         FocusManager.FocusedElement="{Binding RelativeSource={RelativeSource Mode=Self}}" />
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我们设置逻辑焦点,但是当你打开Popup渲染的光标时我们无法打印文本(我建议自己检查).这也可以使用事件处理程序检查Keyboard.GotKeyboardFocus:

private void GotoTextbox_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
    MessageBox.Show("Give focus!");
}
Run Code Online (Sandbox Code Playgroud)

当您Popup打开,消息框不会出现,窗口,当你按下键盘上的键出现.

为了所有工作,它需要设置键盘焦点,它也调用物理焦点.我已经看过许多将Focus设置为TextBox的例子Style.Triggers,但对我来说,由于可理解的原因,它们并不起作用.

我可以建议的唯一解决方案是使用附加行为,它非常适合MVVM的风格.

FocusBehavior

public static class FocusBehavior
{
    public static readonly DependencyProperty IsFocusProperty;

    public static void SetIsFocus(DependencyObject DepObject, bool value)
    {
        DepObject.SetValue(IsFocusProperty, value);
    }

    public static bool GetIsFocus(DependencyObject DepObject)
    {
        return (bool)DepObject.GetValue(IsFocusProperty);
    }

    static FocusBehavior()
    {
        IsFocusProperty = DependencyProperty.RegisterAttached("IsFocus",
                                                              typeof(bool),
                                                              typeof(FocusBehavior),
                                                              new UIPropertyMetadata(false, IsFocusTurn));
    }

    private static void IsFocusTurn(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        var element = sender as Control;

        if (element != null)
        {
            if (e.NewValue is bool && (bool)e.NewValue == true)
            {
                element.Loaded += ElementLoaded;
            }
        }
    }

    private static void ElementLoaded(object sender, RoutedEventArgs e)
    {
        var control = sender as Control;

        if (control != null) 
        {
            if (control is TextBox)
            {
                Keyboard.Focus(control);
            }
            else
            {
                control.Focus();
            }
        }            
    }
}
Run Code Online (Sandbox Code Playgroud)

这里我们为其设置Loaded事件处理程序Control,并将焦点设置为元素.使用此行为的示例:

<Grid>
    <ToggleButton Name="OpenButton"                      
                  Content="Open" 
                  Width="100"
                  Height="30" />

    <Popup Name="PopupGoto"
           StaysOpen="False" 
           PlacementTarget="{Binding ElementName=OpenButton}"
           IsOpen="{Binding Path=IsChecked, ElementName=OpenButton}">           

        <Border>
            <StackPanel>
                <TextBox x:Name="GotoTextbox" 
                         this:FocusBehavior.IsFocus="True"
                         Text="TestText" />

                <Button Content="Goto" />
            </StackPanel>
        </Border>
    </Popup>
</Grid>
Run Code Online (Sandbox Code Playgroud)