2013-08-14 12 views
7

Przeszukałem Google, a tutaj w celu uzyskania odpowiedzi, mój problem jest nieco związany z poniższym pytaniem, ale na tyle odmienny, aby uzasadnić nowe pytanie.WPF: Combobox utrata wybranego indeksu po związanym zmianie kolekcji ItemSource

Combo-box loses selection after collection changes

Zasadniczo mam combobox WPF, który jest związany z klasy ObservableCollection. Ta klasa ma dodatkową funkcjonalność, aby opóźnić powiadamianie o zmianie kolekcji, jeśli muszę wykonać szereg zmian, takich jak czyszczenie i uzupełnianie, aby uzyskać nową migawkę bazy danych.

Moje powiązanie combobox ma zarówno zestaw DisplayMemberPath, jak i SelectedValuePath. SelectedValuePath rozwiązuje właściwość integer.

Problem jest taki sam jak pytanie, do którego się odwołujesz, gdy odświeżam wartości w kolekcji związanej, powiązany składnik ComboBox traci zaznaczenie i jest pusty (SelectedIndex = -1).

Mogę potwierdzić, że zdarzenie CollectionChanged nie zostanie uruchomione, dopóki kolekcja nie zostanie ponownie wypełniona i zawiera elementy z powrotem do niej.

Bardziej zastanawiające jest, jeśli I wykonaj następujące czynności:

 using (_collection.DelayNotifications()) 
     { 
      var items = _collection.ToArray(); 
      _collection.Clear(); 
      _collection.AddRange(items); 
     } 

List rozwijana robi nie stracić swoją wybraną wartość.

Co sugeruje, że ulegnie uszkodzeniu, jeśli elementy w kolekcji zostaną zastąpione nowymi elementami pobranymi z bazy danych - Mogę to zaakceptować, jeśli nie będę używać wiązania SelectedValuePath, ale ponieważ nim jestem i ponieważ wartości całkowite są to samo, z pewnością to, co robię, powinno zadziałać?

Używam .NET 3.5 SP1

Ktoś ma jakieś pomysły?

Edit

Od komentarzach poniżej i odpowiedź blam użytkownika. Zgadzam się, że to jest powód, dla którego robię to. Ale tak naprawdę nie pomaga mi to.

Wiążę właściwość SelectedValue obiektu Combobox z właściwością Integer w moim modelu widoku. Gdybym miał powiązać SelectedItem, musiałbym powiązać z właściwością tego typu obiektu w moim modelu widoku - ale jest to właściwość całkowita, której faktycznie używam.

W tej chwili "naprawiłem" (odczytałem drobny hack) problem, wymuszając zmianę właściwości obiektu dla właściwości "SelectedValue". Wydaje się, że Combobox ponownie sprawdza swoją wewnętrzną listę dla elementu, który pasuje do zdefiniowanej SelectedValuePath.

Funkcja Combobox WPF musi "wiedzieć", że ma ustawiony zestaw wartości SelectedValuePath, dlatego nie sądzę, aby był zbyt daleko, aby można było założyć, że dostosowałaby swoją logikę dopasowywania elementów. Jednak wykracza to poza zakres SO.

Rozumiem, że prawdopodobnie po prostu zaakceptuję to, jak działa WPF, ale po walce z comboboxami związanymi z danymi w WinForms przez kilka lat, miałem nadzieję, że nie będę musiał z WPF :) - choć mówi, że Comboboxe WPF są znacznie lepsze niż WinForm.

+0

ValuePath nie ma znaczenia, jeśli jest to inny obiekt ... Nie można oczekiwać, że wiązanie utrzyma się, ponieważ wiąże się z konkretnymi insances (obiektami). Po ich usunięciu utracono powiązanie ... – UIlrvnd

+0

Metoda usuwania obiektu zwróconego przez DelayNotificatons() podnosi zdarzenie CollectionChange z flagą ListReset. Wciąż zakładam, że combobox będzie przeglądał jego nową listę dla wartości całkowitej, którą może dopasować na ... Jeśli tak nie jest, co się dzieje, jakie są moje opcje? – Marlon

+0

W twoim przykładzie kodu używasz tych samych instancji, ponieważ jedyną rzeczą, którą manipulujesz, są kolekcje. nie będzie wyglądać, ponieważ liczba całkowita jest inną instancją, nawet jeśli ** ma ** tę samą wartość ... Mam nadzieję, że robi się lol ... – UIlrvnd

Odpowiedz

4

To stwierdzenie jest błędne

mogę zaakceptować tego, gdybym nie był przy użyciu SelectedValuePath wiążące, ale ponieważ jestem

Jesteś nie wiązanie z SelectedValuePath.
Powiązanie z kolekcją obiektów.
SelectedValuePath służy wyłącznie do raportowania, nie ma nic wspólnego z porównywaniem obiektów pod kątem równości. DisplayMemberPath służy wyłącznie do raportowania, nie ma nic wspólnego z porównywaniem obiektów pod kątem równości.

Mylić SelectValuePath z SelectedItem.
ComboBox nie używa SelectedValuePath do określenia, czy dwa obiekty są równe.

Z dokumentacji SelectedValuePath:

Pobiera lub ustawia ścieżkę, która jest używana, aby uzyskać SelectedValue z selectedItem.

W próbce że myli ty ładujesz te same obiekty widok.

mam zamiar zakładać SelectedValuePath jest właściwość o nazwie ID

Jeśli jasne i odtworzyć obiekt o ID 6 nie jest równy obiektowi wyczyszczonemu o identyfikatorze 6.

Spróbuj tego. Utwórz dwa obiekty (o1 i o2) o identyfikatorze 6 i porównaj o1.Equals (o2).

Jeśli chcesz, aby dwa obiekty o identyfikatorze 6 były równe, musisz zastąpić GetHashCode i Equals. W polu Zwróć wartość true, jeśli oba mają identyfikator równy 6. Można również użyć identyfikatora jako kodu GetHashCode.

Łańcuch jest typem odniesienia, który oszukuje użytkownika.
string s1 = "cat";
string s2 = "cat";
s1.Equals (s2) zwróci wartość true, ponieważ String Equals zostanie nadpisany, aby porównać wartość.

+0

Tak, rozumiem to, ale ja " m nie wiążę SelectedItem, wiążę do SelectedValue. Dlatego nie spodziewałbym się, że ComboBox porówna równość w SelectedItem.Chociaż domyślam się, że to naprawdę nie może określić, do jakich właściwości ktoś się zobowiązał i dostosować swoją wewnętrzną logikę do pakietu. – Marlon

+0

Jak wyjaśniono w mojej odpowiedzi i komentarzu Stefena no, NIE wiążesz się z SelectedValue. Przywiązujesz się do kolekcji obiektów. DisplayMemberPath i SelectedValuePath służą wyłącznie do raportowania. To jest odpowiedź. Dlaczego odrzucasz go, zamiast go stosować? – Paparazzi

+0

Nie odrzucam tego - po prostu wyjaśniam, co robię. Nie sądzę, że moja logika była tak bezpodstawna. Zobacz moją edycję na pytanie. Dam ci kilka dni, ale prawdopodobnie przyjmuję twoją odpowiedź. – Marlon