Как переместить фокус между различными элементами управления с помощью интерактивного поведения? - PullRequest
0 голосов
/ 03 сентября 2018

У меня есть приложение WPF, в котором у меня есть TextBox и ListBox. Вдохновленный этим SO потоком , я реализовал поведение, позволяющее перемещать фокус с TextBox на ListBox, нажимая клавишу "Вниз". Однако проблема в в том, что это происходит только один раз, то есть OnIsFocusedChanged запускается только один раз. Может кто-нибудь сказать мне, что я скучаю или делаю неправильно?

Вид:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:local="clr-namespace:InteractivityTest"
                xmlns:beh="clr-namespace:InteractivityTest.Behaviors"
                xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity">
    <DataTemplate DataType="{x:Type local:AutoCopmleteTextBoxViewModel}">
        <Grid Name="grMain">
            <TextBox Name="myTextBox"
                     Text="{Binding MyText}"
                     Width="150">
                <i:Interaction.Behaviors>
                    <beh:FocusBehavior IsFocused="{Binding TextBoxHasFocus}" />
                </i:Interaction.Behaviors>

                <TextBox.InputBindings>
                    <KeyBinding Key="Down"
                                Command="{Binding SetFocusToListBoxCommand}" />
                </TextBox.InputBindings>
            </TextBox>

            <Popup Name="puSuggestions"
                   Placement="Bottom"
                   Width="{Binding ElementName=myTextBox, Path=ActualWidth}"
                   MinWidth="0"
                   PlacementTarget="{Binding ElementName=myTextBox}"
                   IsOpen="True">
                <Border Background="White"
                        BorderBrush="Gray"
                        BorderThickness="1"
                        CornerRadius="1">
                    <ListBox Name="lbSuggestions"
                             ItemsSource="{Binding SuggestionCol}"
                             BorderThickness="0"
                             Background="White">
                        <i:Interaction.Behaviors>
                            <beh:FocusBehavior IsFocused="{Binding ListBoxHasFocus}" />
                        </i:Interaction.Behaviors>
                    </ListBox>
                </Border>
            </Popup>
        </Grid>
    </DataTemplate>
</ResourceDictionary>

ViewModel:

Imports System.ComponentModel

Public Class AutoCopmleteTextBoxViewModel
    Implements INotifyPropertyChanged

    Private _SuggestionCol As List(Of String)
    Private _ListBoxHasFocus As Boolean
    Private _TextBoxHasFocus As Boolean

    Public Property SuggestionCol As List(Of String)
        Get
            Return New List(Of String) From {"A", "AB", "ABC", "ABCD"}
        End Get
        Set
            _SuggestionCol = Value
            NotifyPropertyChanged(NameOf(SuggestionCol))
        End Set
    End Property

    Public Property ListBoxHasFocus As Boolean
        Get
            Return _ListBoxHasFocus
        End Get
        Set
            _ListBoxHasFocus = Value
            NotifyPropertyChanged(NameOf(ListBoxHasFocus))
        End Set
    End Property

    Public Property TextBoxHasFocus As Boolean
        Get
            Return _TextBoxHasFocus
        End Get
        Set
            _TextBoxHasFocus = Value
            NotifyPropertyChanged(NameOf(TextBoxHasFocus))
        End Set
    End Property

    Public Property SetFocusToListBoxCommand As ICommand

    Sub New()
        SetFocusToListBoxCommand = New Command(AddressOf Me.OnKeyDownOnTextBox, Nothing)
    End Sub

    Private Sub OnKeyDownOnTextBox(parameter As Object)
        ListBoxHasFocus = True
        TextBoxHasFocus = False
    End Sub

#Region "Property Changed"
    Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged

    Protected Sub NotifyPropertyChanged(info As [String])
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info))
    End Sub
#End Region
End Class

Поведение:

Imports System.Windows.Interactivity

Namespace Behaviors
    Public Class FocusBehavior
        Inherits Behavior(Of Control)

        Public Property IsFocused As Boolean
            Get
                Return CBool(GetValue(IsFocusedProperty))
            End Get
            Set(ByVal value As Boolean)
                SetValue(IsFocusedProperty, value)
            End Set
        End Property
        Public Shared ReadOnly IsFocusedProperty As DependencyProperty =
            DependencyProperty.Register(NameOf(IsFocused), GetType(Boolean),
                                        GetType(FocusBehavior),
                                        New PropertyMetadata(New PropertyChangedCallback(Sub(d, e)
                                                                                             OnIsFocusedChanged(d, e)
                                                                                         End Sub)))

        Private Shared Sub OnIsFocusedChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
            If CBool(e.NewValue) Then
                CType(d, FocusBehavior).GotFocus()
            End If
        End Sub

        Private Sub GotFocus()
            Me.AssociatedObject.Focus()
            Keyboard.Focus(Me.AssociatedObject)
            If TypeOf Me.AssociatedObject Is TextBox Then
                Dim tmpTextBox = TryCast(Me.AssociatedObject, TextBox)
                tmpTextBox.CaretIndex = tmpTextBox.Text.Length
            ElseIf TypeOf Me.AssociatedObject Is ListBox Then
                Dim tmpListBox = TryCast(Me.AssociatedObject, ListBox)
                If Not tmpListBox.Items.Count = 0 Then
                    tmpListBox.SelectedItem = tmpListBox.Items(0)
                    Dim tmpListBoxItem = TryCast(tmpListBox.ItemContainerGenerator.ContainerFromItem(tmpListBox.SelectedItem), ListBoxItem)
                    tmpListBoxItem.Focus()
                End If
            End If
        End Sub
    End Class
End Namespace

1 Ответ

0 голосов
/ 03 сентября 2018

Вы вызываете OnIsFocusedChanged, когда значение свойства зависимости установлено на новое значение, и, похоже, новое значение устанавливается только один раз, в вашем методе OnKeyDownOnTextBox.

Вам необходимо изменить значение свойств источника ListBoxHasFocus и TextBoxHasFocus, чтобы сбрасывать их всякий раз, когда TextBox или ListBox действительно получает фокус.

...