Laden...

ComboBox SelectedItem update - wird aber nicht unmittelbar angezeigt

Erstellt von GeneVorph vor 3 Jahren Letzter Beitrag vor 3 Jahren 1.283 Views
G
GeneVorph Themenstarter:in
180 Beiträge seit 2015
vor 3 Jahren
ComboBox SelectedItem update - wird aber nicht unmittelbar angezeigt

Hallo,

wahrscheinlich ein einfacher Sachverhalt:

Ich habe eine ComboBox, eine TextBox und einen Button.

Die ComboBox enthält Personen-Objecte, die sie aus einer CollectionViewSource erhält. Angezeigt wird jeweils der volle Name einer Person. Die CollectionViewSource wiederum hat als Source eine ObservableCollection<Person>.

Wählt man in der ComboBox eine Person aus, so wird deren Name in der TextBox angezeigt. Der Benutzer kann nun z.B. einen neuen Namen eingeben. Dieser soll jedoch die 'FullName'-Eigenschaft der ausgewählten Person überschreiben, also ein Update vornehmen.

Dazu ist im übrigen der Button, der ein Command (UpdateCommand) feuert.

Nehmen wir an, ich habe "Müller, Peter" ausgewählt.

Ändere ich den Eintrag in der TextBox jetzt ab in "Antoinette, Marie" und betätige den Button, scheint es zunächst, als sei nichts passiert, denn

  • das aktuelle Objekt (SelectedItem) wird zwar im ViewModel in der Command-Methode auf den neuen Wert geupdated, aber in der View ist davon nichts zu sehen.

  • klicke ich auf die ComboBox, so dass sich das DropDown-Feld öffnet sehe ich den alten Eintrag (Müller, Peter) nicht mehr, sondern den neuen (Antoinette, Marie) - gleichzeitig wird aber immer noch im Display der ComboBox 'Müller, Peter' angezeigt.

Meine "LÖsung" bisher: ich setze den Index der ComboBox im ViewModel auf -1 und dann direkt auf den Index des SelectedItem; so erweckt es den Anschein, als sei das Objekt geupdated worden.

Hier mal mein XAML:


<ComboBox ItemsSource="{Binding AllPersonsCV.View}" DisplayMemberPath="FullName" Width="120" 
                          SelectedItem="{Binding SelectedPerson, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" SelectedIndex="{Binding MyIndex}"/>

Und der relevante Code im ViewModel; zuerst für das SelectedItem-Property:

 private Person _selectedPerson;

        public Person SelectedPerson
        {
            get { return _selectedPerson; }
            set
            {
                OnPropertyChanged(ref _selectedPerson, value);
            }

Und die Command-Methode, die das eigentliche Update/Überschreiben vornimmt:



 private void UpdatePerson_Execute(object parameter)
        {
            UpdatePerson();
        }

private void UpdatePerson()
        {
            //Der in die TextBox eingegebene string wird an das Property fullName übergeben und hierdann
            //der FullName-Eigenschaft des SelectedItems der ComboBox übergeben.
            SelectedPerson.FullName = fullName;

           //CollectionViewSource-Refresh
            AllPersonsCV.View.Refresh();
         }
               

Und hier noch mein PersonName-Property, welches an den Text der TextBox gebunden ist:


private string _personName;

public string PersonName
{
   get {return _personName; }
   set
      {
          OnPropertyChanged(ref _personName, value);
      }
}

Soweit habe ich das Problem dann im Debugger schon aufgedröselt:

  • die Werte werden übergeben, d.h. mein SelectedPerson.FullName-Property wird in der UpdatePerson-Methode überschrieben.

  • auch in der AllPersons-ObservableCollection wird dadurch die entsprechende Property des entsprechenden Person-Objekts geändert.

  • da für die View aber meine CollectionViewSource (in der im Debugger auch schon der neue Wert zu sehen is) zuständig ist, refreshe ich die CollectionViewSource.

Trotzdem zeigt das Display-Feld der ComboBox immer noch den alten Wert an. Erst, wenn ich ein anderes Element aus der ComboBox auswähle, ist der alte Wert endgültig verschwunden.

Was mache ich da falsch?

Grüße
Vorph

W
955 Beiträge seit 2010
vor 3 Jahren

Du musst FullName in Person ebenfalls mit einem NotifyPropertyChanged versehen.

G
GeneVorph Themenstarter:in
180 Beiträge seit 2015
vor 3 Jahren

Danke Witte.

Allerdings gibt es da ein Problem: ich habe aus Testzwecken meiner View eine ListView, bzw. ein Label hinzugefügt. Die ListView zeigt alle Elemente der CollectionViewSource an und zwar NUR deren FullName-Property.

Das Label zeigt nur das FullName-Property der SelectedPerson.

Wie oben bereits beschrieben: SelectedPerson ist mein ViewModel-Property für das SelectedItem der ComboBox.

Klicke ich den Button werden die Werte für FullName in der ListView und auch im Label sofort geändert - nur nicht im Textfeld der ComboBox.

Ich denke somit wäre die Implementierung von INotifyPropertyChanged wohl auch nur ein Hack, oder? Funktioniert die ComboBox möglicherweise iwie anders?

5.657 Beiträge seit 2006
vor 3 Jahren

Klicke ich den Button werden die Werte für FullName in der ListView und auch im Label sofort geändert - nur nicht im Textfeld der ComboBox.

Der Bereich ist frei beschreibbar, wenn du das nicht willst, dann setze die IsEditable-Eigenschaft der ComboBox auf False. Siehe dazu die Anmerkungen in der Doku zur ComboBox.

Weeks of programming can save you hours of planning

G
GeneVorph Themenstarter:in
180 Beiträge seit 2015
vor 3 Jahren

IsEditable ist jetzt false - damit kann ich zwar den Bereich nicht mehr beschreiben, aber das eigentliche Problem ist dadurch nicht gelöst: es geht ja darum, dass wenn der Wert in diesem Bereich sich ändert, dies erst angezeigt wird, wenn man vorher ein anderes Item auswählt.

Im DropDown-Bereich wird bereits der neue Wert angezeigt - da das ja ber das aktuelle Item ist, passiert natürlich erst mal nichts, wenn ich diesen sofort auswähle (logischerweise wird in diesem Fall das SelectionChanged-event nicht gefeuert).

4.931 Beiträge seit 2008
vor 3 Jahren

Dann mußt du entweder, so wie du es bisher gemacht hast, ein SelectionChanged auslösen (eben durch zwischenzeitliches Setzen auf -1) oder aber selber die Text-Eigenschaft setzen (wenn IsEditable = true).
Es ist kein übliches Vorgehen, daß sich einzelne Einträge ändern (sondern meistens ändert man ja die komplette Liste und setzt dann die Auswahl neu).

G
GeneVorph Themenstarter:in
180 Beiträge seit 2015
vor 3 Jahren

Es ist kein übliches Vorgehen, daß sich einzelne Einträge ändern (sondern meistens ändert man ja die komplette Liste und setzt dann die Auswahl neu).

Das stimmt natürlich Aber nur, weil es unüblich ist, heißt das ja nicht, dass man nicht eben genau diesen Verhalten im Projekt benötigt:-D

Persönlich würde es mich gar nicht mal stören, weil ich ja weiß, dass der Wert übernommen wurde. Aber ich denke, einen Benutzer würde es irritieren, wenn er z. B. ein Bauteil in einer Liste umbenennt und dann aber den alten Namen angezeigt bekommt.

Aber gut: dann bin ich beruhigt. Kein falsches Binding, kein Denkfehler - einfach nur nicht vorgesehen.

Ich denke, ich bleibe dann beim SelectionChanged. Mercie beaucoup!

Gruß
Vorph

5.657 Beiträge seit 2006
vor 3 Jahren

Einfacher wäre evtl. bei einer Änderung direkt im ViewModel den Text anzupassen, und dann an die ComboBox.Text-Eigenschaft zu binden.

Weeks of programming can save you hours of planning