jpi*_*son 5 wpf focus itemtemplate itemscontrol keyboard-navigation
在焦距和键盘导航方面,我看到了奇怪的行为.在下面的示例中,我有一个简化的ItemsControl,它已经模板化,因此它显示了一个绑定到ItemsSource的CheckBoxes列表.
<ItemsControl FocusManager.IsFocusScope="True"
ItemsSource="{Binding ElementName=TheWindow, Path=ListOStrings}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Run Code Online (Sandbox Code Playgroud)
由于某些奇怪的原因,FocusManager.IsFocusScope ="True"分配导致在通过鼠标单击选中复选框时无法设置键盘焦点,并且当使用空格键选中复选框时,焦点将跳出ItemsControl.键盘.这两个症状似乎都指向选中复选框时发生的一些奇怪的导航,但我很难找到它的底部.
如果我使用此方法将可视树中的任何父元素设置为焦点范围,则会出现此问题.如果我删除了FocusManager.IsFocusScope ="True",那么问题就会消失.不幸的是,我在一个更大的项目中看到了这个问题,我不能仅仅删除这些焦点范围而不必担心其他与焦点相关的后果.
有人可以向我解释我所看到的奇怪行为吗?这是一个错误还是我完全错过了什么?
Fre*_*lad 16
本文非常好地解释了它:http://www.codeproject.com/KB/WPF/EnhancedFocusScope.aspx
FocusScope的设计是什么?
Microsoft在WPF中使用FocusScope来创建临时辅助焦点.WPF中的每个ToolBar和Menu都有自己的焦点范围.
有了这些知识,我们就能清楚地看到为什么会遇到这些问题:
工具栏按钮不应该在自身上执行命令,而是在单击工具栏之前的任何焦点上执行命令.要实现此目的,路由命令会忽略焦点范围的焦点,而是使用"主"逻辑焦点.这解释了为什么路由命令在焦点范围内不起作用.
为什么测试应用程序屏幕截图中的大文本框仍显示插入符号?我不知道答案 - 但为什么不应该呢?当然,文本框没有键盘焦点(WPF焦点范围内的小文本框有); 但它仍然在主动窗口中具有主要的逻辑焦点,并且是所有路由命令的接收器.
这一部分涵盖了您所看到的行为
当您在WPF焦点范围内选中CheckBox并按空格切换时,为什么键盘焦点会移动到大文本框?
嗯,这正是您在单击菜单项或工具栏时所期望的:键盘焦点应该返回到主焦点.所有ButtonBase派生的控件都会执行此操作.
@Meleak很好地解释了这个问题.请阅读文章http://www.codeproject.com/KB/WPF/EnhancedFocusScope.aspx以充分了解问题所在以及如何解决问题.我将添加IsEnhancedFocusScope文章中提到的附加行为的完整实现:
public static class FocusExtensions
{
private static bool SettingKeyboardFocus { get; set; }
public static bool GetIsEnhancedFocusScope(DependencyObject element) {
return (bool)element.GetValue(IsEnhancedFocusScopeProperty);
}
public static void SetIsEnhancedFocusScope(DependencyObject element, bool value) {
element.SetValue(IsEnhancedFocusScopeProperty, value);
}
public static readonly DependencyProperty IsEnhancedFocusScopeProperty =
DependencyProperty.RegisterAttached(
"IsEnhancedFocusScope",
typeof(bool),
typeof(FocusExtensions),
new UIPropertyMetadata(false, OnIsEnhancedFocusScopeChanged));
private static void OnIsEnhancedFocusScopeChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e) {
var item = depObj as UIElement;
if (item == null)
return;
if ((bool)e.NewValue) {
FocusManager.SetIsFocusScope(item, true);
item.GotKeyboardFocus += OnGotKeyboardFocus;
}
else {
FocusManager.SetIsFocusScope(item, false);
item.GotKeyboardFocus -= OnGotKeyboardFocus;
}
}
private static void OnGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) {
if (SettingKeyboardFocus) {
return;
}
var focusedElement = e.NewFocus as Visual;
for (var d = focusedElement; d != null; d = VisualTreeHelper.GetParent(d) as Visual) {
if (FocusManager.GetIsFocusScope(d)) {
SettingKeyboardFocus = true;
try {
d.SetValue(FocusManager.FocusedElementProperty, focusedElement);
}
finally {
SettingKeyboardFocus = false;
}
if (!(bool)d.GetValue(IsEnhancedFocusScopeProperty)) {
break;
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
在您的XAML中,您只需要设置此附加属性而不是标准IsFocusScope属性:
<ItemsControl my:FocusExtensions.IsEnhancedFocusScope="True"
ItemsSource="{Binding ElementName=TheWindow, Path=ListOStrings}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Run Code Online (Sandbox Code Playgroud)
它将按预期的焦点范围工作.
| 归档时间: |
|
| 查看次数: |
6909 次 |
| 最近记录: |