代码之家  ›  专栏  ›  技术社区  ›  Yvonnila

如何使用交互行为在不同控件之间移动焦点?

  •  1
  • Yvonnila  · 技术社区  · 6 年前

    我有一个WPF应用程序,其中我有一个 TextBox 和一个 ListBox . 灵感来自 this SO thread ,我实现了一个行为,以一种我可以将焦点从 文本框 列表框 问题是 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>
    

    视图模型:

    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 回复  |  直到 6 年前
        1
  •  3
  •   mm8    6 年前

    你在打电话吗 OnIsFocusedChanged 当dependency属性的值设置为 OnKeyDownOnTextBox 方法。

    您需要更改 ListBoxHasFocus TextBoxHasFocus 源属性,以便在 TextBox 或者 ListBox