Используйте ListBox в фокусе - PullRequest
7 голосов
/ 05 января 2012

Короткая история: 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);
        }
    }
}

Итак:

  1. Есть ли способ заставить ListBox работать в пределах области фокусировки?

  2. Или есть другой элемент управления списком, который лучше работает внутри фокусасфера?

  3. Или я выбрал неправильный подход с помощью фокуса?Мои требования: пользователь должен иметь возможность выбрать элемент из прокручиваемого списка, который введет значение в текущее поле.Текущее поле не должно терять фокус.

Ответы [ 2 ]

2 голосов
/ 10 января 2012

Мой ответ будет: не используйте для этого фокусную область .

Вы как бы побеждаете цель фокусировки.Что если кто-то не может использовать мышь и хочет вместо этого использовать клавиатуру?

Почему бы просто не выделить элемент в списке, а затем вернуть фокус обратно к исходному элементу управления вместо выполнения всей этой дополнительной работы с областями фокусировки?

1 голос
/ 10 января 2012

Когда вы щелкаете по ListBox или элементу, который он содержит, вы устанавливаете фокус клавиатуры вашего приложения на ListBox.Это происходит независимо от того, какие области фокусировки вы определили.

Можно определить область фокусировки для верхней панели (той, которая содержит поля) и иметь ListBox's 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 и настройку фокуса на него.

Я предполагаювы знакомы с терминами, которые я использовал (фокус клавиатуры / логический фокус);если нет, вы можете взглянуть на Обзор фокуса или просто спросить.

...