Frage

Ich habe einen Expander in der ItemTemplate einer Listbox. Macht gut. Das Problem, auf das ich gestoßen bin, ist, dass ich möchte, dass das Ereignis von Listbox_SelectionChanged feuert, wenn der Expander erweitert und/oder ausgewählt wird. Das MouseDown -Ereignis scheint nicht in die Listbox zu sprudeln.

Was ich brauche, ist der ausgewählteIndex der Listbox. Da die Listbox_SelectionChanged nicht abgefeuert wird, ist der Index -1 und ich kann nicht bestimmen, welches Element ausgewählt wurde.

Das Ereignis von Listbox_SelectionChanged wird abgefeuert, wenn ein Benutzer nach der Erweiterung auf den Inhalt des Expander klickt. Wenn sie nur auf den Expander klicken, wird das Ereignis nicht abgefeuert. Dies ist für den Benutzer verwirrend, da sie visuell glauben, dass er bereits auf diesen Artikel geklickt hat, wenn er tatsächlich auf den Expander -Header klickt. Ich benötige das Listbox -Element ausgewählt, wenn der Benutzer den Expander erweitert, da der Benutzer in Bezug auf den Benutzer jetzt ausgewählt wird, wenn dies nicht der Fall ist.

Irgendwelche Vorschläge, wie dies funktioniert oder alternative Möglichkeiten zur Bestimmung des SelectedIndex des Listenfelds mit expandierten darin ermittelt werden können?

Vereinfachter Code als Referenz:

<Window x:Class="WpfApplication3.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300"
    Loaded="Window_Loaded">
    <Grid Name="Root">
        <ScrollViewer>
            <ListBox SelectionChanged="ListBox_SelectionChanged" ItemsSource="{Binding}">
                <ItemsControl.ItemTemplate >
                    <DataTemplate>
                        <Border>
                            <Expander>
                                <Expander.Header>
                                    <TextBlock Text="{Binding Path=Name}"/>
                                </Expander.Header>
                                <Expander.Content>
                                    <StackPanel>
                                        <TextBlock Text="{Binding Path=Age}"/>
                                        <TextBlock Text="Line 2"/>
                                        <TextBlock Text="Line 3"/>
                                    </StackPanel>
                                </Expander.Content>
                            </Expander>
                        </Border>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ListBox>
        </ScrollViewer>
    </Grid>
</Window>

Einfache Klasse zur Bindung:

public class Person
{
    public string Name {
        get;
        set;
    }

    public int Age {
        get;
        set;
    }
}

Erstellen und Füllen der Daten zur Bindung:

private void Window_Loaded(object sender, RoutedEventArgs e) {

    data = new ObservableCollection<Person>();

    data.Add(new Person {
        Name = "One",
        Age=10
    });

    data.Add(new Person {
        Name = "Two",
        Age = 20
    });

    data.Add(new Person {
        Name = "Three",
        Age = 30
    });

    Root.DataContext = data;
}

Dies ist das Ereignis, das ich brauche (wirklich nur der ausgewählteIndex, den ich brauche)

private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) {
    ListBox box = (ListBox)sender;

    // This value is not set because events from Expander are not bubbled up to fire SelectionChanged Event
    int index = box.SelectedIndex;
}
War es hilfreich?

Lösung

Eine alternative Art und Weise, die nicht von der ausgewählten Auswahl abhängt. Sie können ein erweitertes/kollabiertes Ereignis des Expanders an den Code dahinter anschließen und den folgenden Code verwenden, um den Listbox -Index zu finden, auf den Sie geklickt haben.

DependencyObject dep = (DependencyObject)e.OriginalSource;

while ((dep != null) && !(dep is ListViewItem))
{
   dep = VisualTreeHelper.GetParent(dep);
}

if (dep == null)
     return;

int index = yourListBox.ItemContainerGenerator.IndexFromContainer(dep);

Andere Tipps

Was Sie wollten, ist, dass die Expander -Steuerung die Listbox -Auswahl steuert. Sie können dies problemlos archivieren, indem Sie eine zweiwertige Bindung auf der ISEXPanded -Eigenschaft des Expanders an die unmittelbare ListBoxItem -, auf die Sie geklickt haben, festlegen.

 <Expander IsExpanded="{Binding IsSelected,Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}">

Update: Wenn Sie bei der Auswahl eines anderen Elements den automatischen Zusammenbruch vermeiden müssen, erstellen Sie den Listbox -Auswahlmodus für mehrere.

<ListBox SelectionMode="Multiple"

Danke Jobi. Das ist ziemlich klug. Das Kaninchenloch von WPF wird immer tiefer.

Hier ist, was ich auf Ihrem Vorschlag gemacht habe:

private void Expander_Expanded(object sender, RoutedEventArgs e) {
    DependencyObject dep = (DependencyObject)sender;

    while ((dep != null) && !(dep is ListBoxItem)) {
        dep = VisualTreeHelper.GetParent(dep);
    }

    if (dep == null)
        return;

    int index = PersonList.ItemContainerGenerator.IndexFromContainer(dep);

    PersonList.SelectedIndex = index;
}

private void Expander_Collapsed(object sender, RoutedEventArgs e) {
    DependencyObject dep = (DependencyObject)sender;

    while ((dep != null) && !(dep is ListBoxItem)) {
        dep = VisualTreeHelper.GetParent(dep);
    }

    if (dep == null)
        return;

    int index = PersonList.ItemContainerGenerator.IndexFromContainer(dep);

    if (PersonList.SelectedIndex == index)
        PersonList.SelectedIndex = -1;
}

Ich musste das ListViewItem in ListBoxItem ändern (ich verwendete eine Listbox).

Außerdem habe ich den Index verwendet, um die Listbox.SelectedIndex auszuwählen oder auszuwählen. Dies gibt mir die Erfahrung, nach der ich gesucht habe.

  1. Wenn jemand einen Expander erweitert, wählt er das neu erweiterte ListBoxItem aus.

  2. Wenn jemand einen anderen Expander erweitert, wird das vorherige ListBoxItem abgewählt, aber erweitert, das neu erweiterte ListBoxItem wird ausgewählt.

  3. Wenn jemand einen ausgewählten Expander zusammenbricht, wird das ListBoxItem abgewählt.

  4. Wenn mehrere Erweiterungen erweitert sind, kollabiert jemand einen nicht ausgewählten ListBoxItem-Expander, das zuvor ausgewählte ListBoxItem bleibt ausgewählt.

Vielen Dank für die Hilfe - ich denke, dies ist ein sehr nützliches kleines Code -Snippet für alle, die Expandierungen in einer Listbox verwenden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top