【问题标题】:How to move focus between different controls using Interactivity Behavior?如何使用交互行为在不同控件之间移动焦点?
【发布时间】:2018-09-03 13:58:29
【问题描述】:

我有一个 WPF 应用程序,其中有一个 TextBox 和一个 ListBox。受this SO thread 的启发,我实现了一个行为,通过按下向下键,我可以将焦点从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>

视图模型:

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

【问题讨论】:

  • 当 TextBoxHasFocus 的值设置为 new 值时,您似乎正在调用 OnIsFocusedChanged。
  • @mm8 我想我没有完全理解你的意思..
  • @Yvonilla:您将 TextBoxHasFocus 属性设置为 false,然后设置了您的依赖项属性,但是您在哪里将其设置为 true?
  • @mm8 是的,你是对的!似乎我一直在混淆我的焦点属性(TextBoxHasFocus)和对文本框的真正关注。非常感谢!

标签: .net wpf vb.net mvvm attachedbehaviors


【解决方案1】:

当依赖属性的值设置为 new 值时,您正在调用 OnIsFocusedChanged,并且它似乎只在您的 OnKeyDownOnTextBox 方法中设置为新值一次。

您需要更改ListBoxHasFocusTextBoxHasFocus 源属性的值,以便在TextBoxListBox 实际获得焦点时重置它们。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-10
    • 2016-05-14
    • 1970-01-01
    • 2014-01-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多