[Wpf] Wenn Sie ein Textfeldelement in einem Listenfeld auswählen, wird das ausgewählte Element des Listenfelds nicht geändert


Answers

Wir verwenden den folgenden Stil, um einen PreviewGotKeyboardFocus festzulegen, der alle Ereignisse des TextBox-Steuerelements und der ComboBoxen behandelt:

    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <EventSetter Event="PreviewGotKeyboardFocus" Handler="SelectCurrentItem"/>
        </Style>
    </ListView.ItemContainerStyle>

Und dann wählen wir die Zeile im Code hinter:

    protected void SelectCurrentItem(object sender, KeyboardFocusChangedEventArgs e)
    {
        ListViewItem item = (ListViewItem) sender;
        item.IsSelected = true;
    }
Question

Ich habe eine WPF-Listbox, die eine Liste von Textboxen anzeigt. Wenn ich auf die Textbox klicke, ändert sich die Listbox-Auswahl nicht. Ich muss neben dem Textfeld klicken, um den Listeneintrag auszuwählen. Gibt es eine Eigenschaft, die ich für das Textfeld festlegen muss, um das Klickereignis an die Listbox weiterzuleiten?




Ich bin mir nicht ganz sicher, ob Sie die Auswahl direkt vornehmen möchten, wie in der vorherigen Antwort beschrieben, weil ich denke, dass sie die Multiselektion und einige andere Szenerien unterbrechen würde

. Vielleicht möchten Sie versuchen, eine Schaltfläche wie unten neu zu formatieren und zu sehen, was passiert.

<Button ClickMode="Pressed" Focusable="False">
<Button.Template>
    <ControlTemplate>  // change the template to get rid of all the default chrome 
        <Border Background="Transparent"> // Button won't be clickable without some kind of background set
            <ContentPresenter />
        </Border>
    </ControlTemplate>
</Button.Template>
<TextBox />




Das Folgende ist eine Vereinfachung von @ Bens Antwort, ohne das DataTemplate überschreiben zu müssen. Es kann sogar als statischer Stil angewendet werden. Getestet mit einer ListView, die eine GridView > GridViewColumn > TextBox .

Beispiel:

<ListView.Resources>
    <Style TargetType="{x:Type ListViewItem}">
        <Style.Triggers>
            <Trigger Property="IsKeyboardFocusWithin" Value="True">
                <Setter Property="IsSelected" Value="True"></Setter>
            </Trigger>
        </Style.Triggers>
    </Style>
</ListView.Resources>



Ich habe ähnlich wie Roberts Lösung gearbeitet, aber ohne Code dahinter (mit angehängtem Verhalten).

Um dies zu tun,

Zuerst. Erstellen Sie eine separate Klasse FocusBehaviour:


using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace MyBehaviours
{
    public class FocusBehaviour
    {
        #region IsFocused
        public static bool GetIsFocused(Control control)
        {
            return (bool) control.GetValue(IsFocusedProperty);
        }

        public static void SetIsFocused(Control control, bool value)
        {
            control.SetValue(IsFocusedProperty, value);
        }

        public static readonly DependencyProperty IsFocusedProperty = DependencyProperty.RegisterAttached(
            "IsFocused", 
            typeof(bool),
            typeof(FocusBehaviour), 
            new UIPropertyMetadata(false, IsFocusedPropertyChanged));

        public static void IsFocusedPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            var control = sender as Control;
            if (control == null || !(e.NewValue is bool))
                return;
            if ((bool)e.NewValue && !(bool)e.OldValue)
                control.Focus();
        }

        #endregion IsFocused

        #region IsListBoxItemSelected

        public static bool GetIsListBoxItemSelected(Control control)
        {
            return (bool) control.GetValue(IsListBoxItemSelectedProperty);
        }

        public static void SetIsListBoxItemSelected(Control control, bool value)
        {
            control.SetValue(IsListBoxItemSelectedProperty, value);
        }

        public static readonly DependencyProperty IsListBoxItemSelectedProperty = DependencyProperty.RegisterAttached(
            "IsListBoxItemSelected", 
            typeof(bool),
            typeof(FocusBehaviour), 
            new UIPropertyMetadata(false, IsListBoxItemSelectedPropertyChanged));

        public static void IsListBoxItemSelectedPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            var control = sender as Control;
            DependencyObject p = control;
            while (p != null && !(p is ListBoxItem))
            {
                p = VisualTreeHelper.GetParent(p);
            } 

            if (p == null)
                return;

            ((ListBoxItem)p).IsSelected = (bool)e.NewValue;
        }

        #endregion IsListBoxItemSelected
    }
}

Zweite. Fügen Sie einen Stil im Ressourcenbereich hinzu (mein Stil ist im Fokus schwarz gerundet). Benachrichtigungssetter für die FocusBehaviour.IsListBoxItemSelected-Eigenschaft. Du solltest es in xmlns:behave="clr-namespace:MyBehaviours" referenzieren xmlns:behave="clr-namespace:MyBehaviours"

`

    <Style x:Key="PreviewTextBox" BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
        <Setter Property="BorderThickness" Value="1"/>
        <Setter Property="Padding" Value="1"/>
        <Setter Property="AllowDrop" Value="true"/>
        <Setter Property="Background" Value="White"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TextBox}">
                    <Border
                        Margin="6,2,0,4"
                        BorderBrush="#FFBDBEBD"
                        BorderThickness="1"
                        CornerRadius="8"
                        Background="White"
                        VerticalAlignment="Stretch"
                        HorizontalAlignment="Stretch"
                        MinWidth="100"
                        x:Name="bg">
                        <ScrollViewer 
                            x:Name="PART_ContentHost" 
                            SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsKeyboardFocusWithin" Value="True">
                            <Setter Property="Background" TargetName="bg" Value="Black"/>
                            <Setter Property="Background" Value="Black"/><!-- we need it for caret, it is black on black elsewise -->
                            <Setter Property="Foreground" Value="White"/>
                            <Setter Property="behave:FocusBehaviour.IsListBoxItemSelected" Value="True"/>
                        </Trigger>

                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

`

Dritte. (optional, für umgekehrte Aufgabe)

Sie werden, wenn nicht, eine Reverse-Aufgabe treffen, die sich auf TextBox konzentriert, wenn ListBoxItem ausgewählt wird. Ich empfehle, eine andere Eigenschaft der Behavior-Klasse IsFokussiert zu verwenden. Hier ist eine Beispielvorlage für ListBoxItem , ListBoxItem Sie bitte Property="behave:FocusBehaviour.IsFocused" und FocusManager.IsFocusScope="True"

    <DataTemplate x:Key="YourKey" DataType="{x:Type YourType}">
            <Border
            Background="#FFF7F3F7"
            BorderBrush="#FFBDBEBD"
            BorderThickness="0,0,0,1"
            FocusManager.IsFocusScope="True"
            x:Name="bd"
            MinHeight="40">
                <TextBox
                    x:Name="textBox"
                    Style="{StaticResource PreviewTextBox}"
                    Text="{Binding Value}" />
        </Border>
        <DataTemplate.Triggers>
            <DataTrigger
                Binding="{Binding IsSelected,RelativeSource={RelativeSource AncestorType=ListBoxItem}}"
                Value="True">
                <Setter
                    TargetName="textBox"
                    Property="behave:FocusBehaviour.IsFocused" 
                    Value="True" />
            </DataTrigger>
        </DataTemplate.Triggers>
    </DataTemplate>






Gibt es eine Eigenschaft, die ich für das Textfeld festlegen muss, um das Klickereignis an die Listbox weiterzuleiten?

Es ist keine einfache Eigenschaft, aber Sie können das GotFocus Ereignis in Ihrem TextBox und anschließend mit VisualTreeHelper das ListBoxItem Objekt suchen und auswählen:

private void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
    TextBox myTextBox = sender as TextBox;
    DependencyObject parent = VisualTreeHelper.GetParent(myTextBox);
    while (!(parent is ListBoxItem))
    {
        parent = VisualTreeHelper.GetParent(parent);
    }
    ListBoxItem myListBoxItem = parent as ListBoxItem;
    myListBoxItem.IsSelected = true;
}



Probieren Sie diesen Code aus:

foreach (object item in this.listBox1.Items) {
    if (textbox1.text.equals(item.toString())) {
        //show error message; break
    }
}