Laden...

Strg + A ändert im ViewModel nur teilweise auf IsSelected?

Erstellt von BlackMatrix vor 11 Jahren Letzter Beitrag vor 11 Jahren 1.912 Views
B
BlackMatrix Themenstarter:in
218 Beiträge seit 2012
vor 11 Jahren
Strg + A ändert im ViewModel nur teilweise auf IsSelected?

Ich habe in meinem AllCustomerView eine ListView, die mir die verfügbaren Customer anzeigt. Auf die ListView habe ich ein ContextMenu gelegt, sodass man über dieses verschiedene Methoden der Customer ausführen kann.

    <UserControl.Resources>
        <Style x:Key="CustomerItemStyle" TargetType="{x:Type ListViewItem}">
            <Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}" />
        </Style>
    </UserControl.Resources>

<ListView 
			ItemContainerStyle="{StaticResource CustomerItemStyle}"
			ItemsSource="{Binding AllCustomers}"              
        >
            <ListView.ContextMenu>
                <ContextMenu>

                    <MenuItem
						Header="Register"
						Command="{Binding RegisterCommand}"
                    />
<!-- etc -->

Im AllCustomerViewModel rufe ich dann folgende Funktion auf. Es sollen die markieren Einträge über das ContextMenu registriert werden.


        private void Register()
        {
            foreach (CustomerViewModel customerViewModel in AllCustomers.Where(customerViewModel => customerViewModel.IsSelected))
                ThreadPool.QueueUserWorkItem(delegate { customerViewModel.Register(); });
        }

Hat jemand eine Erklärung, wieso ich über STRG + A nicht dafür sorgen kann, dass alle Customer registriert werden? Es werden nur ein paar registriert, wahrscheinlich nur die, die für den Nutzer sichtbar sind. Wenn ich aber den ersten Customer markiere und dann mittels Shift + Bild unten alle markiere, werden alle registriert 😕

edit: Okay, irgendwas stimmt nicht mit der Bindung von IsSelected. Wie bindet man denn IsSelected richtig ans ViewModel? Wenn ich 3 Elemente markiert habe und diese nicht mehr im aktuellen Ausschnitt sichtbar sind, dann möchte ich diese immer deselektieren, wenn ich mit der linken Maustaste auf ein anderes einzelnes Element klicke. Das ist nämlich im Moment nicht der Fall.

5.299 Beiträge seit 2008
vor 11 Jahren

Okay, irgendwas stimmt nicht mit der Bindung von IsSelected. Keine Ahnung. Ich hab grad son Listview genau in dem Stil gebaut, und das arbeitet zuverlässig.

Allerdings deine Anforderung "Items ausserhalb des sichtbaren Bereichs bei MausLinksklick deselectieren" scheint mir schwierig, und ich denke, da hast du iwelche Bugs drinne.
Normal-Verhalten ist ja, dass bei LinksKlick alle Items deselektiert (bis auf das geklickste) werden, egal ob sichtbar oder nicht.

Der frühe Apfel fängt den Wurm.

B
BlackMatrix Themenstarter:in
218 Beiträge seit 2012
vor 11 Jahren

Probiere mal folgendes:

Lege eine ListView mit mehreren Elementen an, sodass du scrollen musst um die anderen Elemente zu sehen. Nun markierst du ein Element, scrollst dieses aus dem Sichtbereich und markierst dort ein Element. Du hast nun 2 Elemente markiert, das untere, welches nicht mehr sichtbar ist und das gerade Markierte. Das ist kein typisches Verhalten und hat wohl irgendwas mit Virtualization zu tun. Leider habe ich bisher noch keine sinnvolle Möglichkeit gefunden, das richtig zu stellen.

Was man machen könnte, die ganzen Tastenkombinationen im ViewModel zu Binden, aber irgendwie hab ich das Gefühl, dass man damit nicht 100% die Funktionalität wie in jedem x-beliebigen Explorer hinbiegt.

1.378 Beiträge seit 2006
vor 11 Jahren

Hallo BlackMatrix,

ich kenne das Verhalten welches du beschreibst. In dem Thread How to bind IsSelected in a ListView for non-visible (virtualized) items wird auf eine Lösung im Codebehind verwiesen bei der man das SelectionChanged Event abboniert und dort dann die Selektionen manuel setzt.

Lg, XXX

B
BlackMatrix Themenstarter:in
218 Beiträge seit 2012
vor 11 Jahren

Das macht natürlich Sinn und da es sich ja nur um UI-Logik handelt, gehört es da auch hin.

Ich hab nun

<UserControl.Resources>
        <Style x:Key="CustomerItemStyle" TargetType="{x:Type ListViewItem}">
            <Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}" />
        </Style>
    </UserControl.Resources>

vollständig entfernt und

    <ListView 
			ItemsSource="{Binding AllAccounts}"  
            SelectionChanged="ListView_SelectionChanged"
        >
        private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            foreach (CustomerViewModel vm in ((ListView)sender).Items)
            {
                if (e.AddedItems.Contains(vm))
                    vm.IsSelected = true;
                else
                    vm.IsSelected = false;
            }
        }

hinzugefügt und es scheint zu funktionieren.

B
BlackMatrix Themenstarter:in
218 Beiträge seit 2012
vor 11 Jahren

@xxxprod:

Wie hast du die Selektionen gesetzt? Ich habe teilweise immer noch komische Verhalten 😦

1.378 Beiträge seit 2006
vor 11 Jahren

Hallo BlackMatrix,

ich habe das selber noch nie benötigt sondern nur ein Beispiel für dich im Netz gegoogelt. Was für ein komisches Verhalten bemerkst du denn? Mir fällt bei deinem Codeschnippsel nur auf, dass du immer alle Items durchiterierst und IsSelected setzt. Vielleicht ändert sich ja das Verhalten schon, wenn du nur die "AddedItems" und "RemovedItems" aus der SelectionChangedEventArgs-Klasse behandelst.

Lg, XXX

B
BlackMatrix Themenstarter:in
218 Beiträge seit 2012
vor 11 Jahren

Stimmt, das wäre natürlich von der Logik her sinnvoller, nur die Elemente anzupacken bei denen auch wirklich die Selektierung geändert wurde.

Naja, das Problem war das immer noch Elemente markiert waren, die es eigentlich nicht sein sollten.

Ich hatte den Code dahingehend abgeändert:

                private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            foreach (CustomerViewModel vm in ((ListView)sender).Items)
            {
                if (e.AddedItems.Contains(vm))
                    vm.IsSelected = true;
                else if(e.RemovedItems.Contains(vm)
                    vm.IsSelected = false;
            }
        }

Des Weiteren hatte ich ein Problem bei der Filterung und dem IsSelected. Ich habe eine bestimmte Menge im ListViewControl markiert, dann habe ich über eine Textbox die Elemente gefiltert und anschließend erstmal alle Selektionen im ViewModel entfernt. Somit muss der Benutzer erneut markieren.

Was mich daran gestört hat. Ich muss in der View und im ViewModel daran denken, dass immer richtig selektiert ist.

Die Frage ist, wie ist eigentlich die intuitive bzw. die von Windows standardisierte Vorgehensweise? Wird bei einer Filterung automatisch jegliche Selektion entfernt, sind nur noch die Elemente markiert, die durch den Filter durchkommen und/oder muss ich die Markierung von den Elementen wieder herstellen, sobald der Filter wieder herausgenommen wird?

1.378 Beiträge seit 2006
vor 11 Jahren

Bzgl. der Items die trotzdem selektiert bleiben fällt mir leider gerade nichts mehr dazu ein.

Bzgl. der Vorgehensweise glaub ich, dass das Geschmackssache ist: Ich hab zum Beispiel mal eine Filterfunktion umgesetzt, die sich nur die sichtbaren Items merkt. Wenn der Filter wieder aufgelöst wird, sind nur die zuletzt markierten Elemente wieder markiert.

Falls das mit den virtuellen Items und dem IsSelected nicht hinhauen mag, bleibt dir denke ich nicht mehr viele Optionen.
Eine wäre, die nicht-funktionierende Logik selber nachzufrickeln. Zb. Bei einem ItemSelected auch noch prüfen ob die Shift Taste gedrückt war usw. Aber das ist nicht wirklich eine schöne Lösung. Oder du findest ein anderes Control das damit besser zurecht kommt.

Lg, XXX