我有以下但触发器无效。它应该将光标放在准备输入的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>
答案 0 :(得分:6)
FocusManager.FocusedElement
为元素建立了逻辑焦点:
确定附加此属性的元素是否具有逻辑焦点。
这是什么意思?这意味着,在WPF中有两个与焦点相关的主要概念:键盘焦点和逻辑焦点[MSDN
]。以下是一个例子:
<TextBox Name="GotoTextbox"
Text="TestText"
Keyboard.GotKeyboardFocus="GotoTextbox_GotKeyboardFocus"
FocusManager.FocusedElement="{Binding RelativeSource={RelativeSource Mode=Self}}" />
在这种情况下,我们设置逻辑焦点,但是当你打开Popup
时,光标会被渲染,我们无法打印文本(我建议你自己检查)。这也可以使用事件处理程序Keyboard.GotKeyboardFocus
检查:
private void GotoTextbox_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
MessageBox.Show("Give focus!");
}
当您Popup
打开时,MessageBox不会出现,当您按下键盘上的按键时会出现窗口。
对于所有正常工作,需要设置键盘焦点,它还调用物理焦点。我在Style.Triggers
中看到过很多关于设置Focus to TextBox的例子,但对我来说,由于可以理解的原因,它们并不起作用。
我可以建议的唯一解决方案是使用附加行为,它非常适合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();
}
}
}
}
这里我们为Control
设置Loaded事件处理程序,并将焦点设置为元素。使用此行为的示例:
<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>
答案 1 :(得分:1)
您的代码几乎正确无误。只需将Setter.TargetName设置为与Value绑定相同,一切都会正常工作。
<Setter Property="FocusManager.FocusedElement" Value="{Binding ElementName=GotoTextbox}" ElementName="GotoTextbox" />