在焦点范围内使用ListBox
本文关键字:ListBox 范围内 焦点 | 更新日期: 2023-09-27 18:19:27
短篇故事:焦点范围内的ListBox不允许选择项目。
长话短说:
我正在尝试为数据输入制作一个上下文敏感的小部件。我有一个包含几个字段的主面板。下面,我有一个带有FocusManager.FocusScope="True"
的面板。该面板将填充当前具有焦点的字段的相关小部件。例如,选择日期字段会在屏幕底部显示日历。
我有几个控件,要求用户从列表中选择多个值中的一个。我将ListBox放入焦点范围,但无法选择任何项目。当(以编程方式)选择某个内容并单击ListBox时,它将取消选择所有内容。
我测试了一些事件,它没有选择MouseDown事件,但它选择了MouseMove事件。每当我点击一个项目时,它就会触发GotFocus,但它从不触发LostFocus。我不确定这意味着什么,但我希望它能对正在阅读这篇文章的人有所帮助。
以下是我用来显示上下文相关小部件的代码。我的窗口中有以下XAML:
<Grid x:Name="EntryWidget" FocusManager.IsFocusScope="True">
<Grid.Resources>
<ListBox x:Key="List" ItemsSource="{Binding}" />
</Grid.Resources>
</Grid>
我使用Window.GotFocus路由事件将小部件更新到适当的控件,如下所示:
private void Window_GotFocus(object sender, RoutedEventArgs e)
{
FrameworkElement focus = (FrameworkElement)FocusManager.GetFocusedElement(this);
EntryWidget.Children.Clear(); // Could this be the culprit?
object tag = focus.Tag;
if (tag != null)
{
if (EntryWidget.Resources.Contains(tag))
{
EntryWidget.Children.Add(EntryWidget.Resources[tag] as UIElement);
}
}
}
因此:
有没有办法让ListBox在焦点范围内工作?
或者还有其他列表控件在焦点范围内工作得更好吗?
还是我使用焦点范围采取了错误的方法?我的要求:用户必须能够从可滚动列表中选择一个项目,该列表将在当前字段中输入值。当前领域不应失去焦点。
我的答案是对此不使用焦点范围。
你有点违背了专注的目的。如果有人不能使用鼠标而想使用键盘怎么办?
为什么不在列表中进行选择,然后将焦点设置回原始控件,而不是使用焦点范围进行所有这些额外的工作?
当您单击ListBox或它包含的项目时,您正在将应用程序的键盘焦点设置为ListBox。无论您定义的焦点范围如何,都会发生这种情况。
可以为上部面板(包含字段的面板)定义焦点范围,并将ListBox的SelectionChanged
焦点设置为上部面板,这实际上会将焦点设置为在单击任何ListBox项目之前在该面板中聚焦的项目。
<StackPanel>
<StackPanel x:Name="upperPanel" FocusManager.IsFocusScope="True" GotFocus="upperPanel_GotFocus">
<TextBox x:Name="TextBox1"></TextBox>
<TextBox x:Name="TextBox2"></TextBox>
</StackPanel>
<StackPanel>
<ListBox x:Name="ListBox1" SelectionChanged="ListBox_SelectionChanged">
<ListBoxItem>First</ListBoxItem>
<ListBoxItem>Second</ListBoxItem>
<ListBoxItem>Third</ListBoxItem>
</ListBox>
<ListBox x:Name="ListBox2" SelectionChanged="ListBox_SelectionChanged">
<ListBoxItem>4</ListBoxItem>
<ListBoxItem>5</ListBoxItem>
<ListBoxItem>6</ListBoxItem>
</ListBox>
</StackPanel>
</StackPanel>
private IInputElement focusedElement = null;
private void upperPanel_GotFocus(object sender, RoutedEventArgs e)
{
focusedElement = e.Source as IInputElement;
}
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
UpdateTextBoxValue((e.AddedItems[0] as ListBoxItem).Content.ToString());
}
private void UpdateTextBoxValue(string text)
{
TextBox focusedTextBox = focusedElement as TextBox;
if (focusedTextBox != null)
{
focusedTextBox.Text = text;
}
upperPanel.Focus();
}
upperPanel
作用域中的当前活动控件由GotFocus
事件处理程序保持最新,UpdateTextBoxValue
方法负责设置活动TextBox
控件上的文本并将焦点设置回该控件。
我假设你熟悉我使用的术语(键盘焦点/逻辑焦点);如果没有,你可以看看焦点概述,或者你可以问。