在Focus范围内使用ListBox

小故事:焦点范围内的ListBox不允许选择项目。

很长的故事:

我正在尝试为数据输入创建一个上下文敏感的小部件。 我有几个领域的主面板。 在那之下,我有一个FocusManager.FocusScope="True"的面板。 此面板将填充当前具有焦点的相关窗口小部件。 例如,选择日期字段将在屏幕底部显示日历。

我有几个控件,要求用户从列表中选择多个值中的一个。 我把一个列表框放到焦点范围内,但我不能选择任何项目。 当选择某项(以编程方式)并单击列表框时,它将取消选择所有内容。

我测试了一些事件,并且没有拾取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的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控件上的TextBox并将焦点设置回它。

    我假设你熟悉我使用的术语(键盘焦点/逻辑焦点); 如果没有,你可以看看焦点总览,或者你可以问。

    链接地址: http://www.djcxy.com/p/10275.html

    上一篇: Use ListBox within Focus Scope

    下一篇: SafeMM for Delphi XE2