Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
[Gelöst] - MVVM - SelectedItem für ItemsSource setzen (Memory Problem)
_Cashisclay
myCSharp.de - Member



Dabei seit:
Beiträge: 279

Themenstarter:

[Gelöst] - MVVM - SelectedItem für ItemsSource setzen (Memory Problem)

beantworten | zitieren | melden

Hallo zusammen,

ich hab aktuell das Problem das manche SelectedItems nicht gesetzt werden, weil anscheinend die ItemsSource zu spät geladen wird, wie kann ich denn am besten die Daten laden bevor der DataContext gesetzt wurde?

Grüße
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von _Cashisclay am .
private Nachricht | Beiträge des Benutzers
pinki
myCSharp.de - Member

Avatar #avatar-4072.jpg


Dabei seit:
Beiträge: 695
Herkunft: OWL

beantworten | zitieren | melden

Hallo,
da die SelectedItems aus der ItemsSource-Auflistung stammen müssen, sind dir die doch eh erst bekannt, nachdem die Objekte der ItemsSource geladen wurden.
Wie meinst du das genau?

Gruß
private Nachricht | Beiträge des Benutzers
_Cashisclay
myCSharp.de - Member



Dabei seit:
Beiträge: 279

Themenstarter:

beantworten | zitieren | melden

Hallo,

            public List<ClinicModel>                    ComboBoxMaterialPreparationProtocolsClinicItemsSource
            {
                get
                {
                    return _ComboBoxMaterialPreparationProtocolsClinicItemsSource;
                }
            }

            public ClinicModel                          ComboBoxMaterialPreparationProtocolsClinicSelectedItem
            {
                get { return Item.Clinic != null ? Item.Clinic : null; }
                set
                {
                    Item.Clinic = value;
                    Raise(nameof(ComboBoxMaterialPreparationProtocolsClinicSelectedItem));

                        Raise(nameof(LabelMaterialPreparationProtocolsAdditionalRequirementContent));
                }
            }

            public ICommand                             ComboBoxMaterialPreparationProtocolsClinicSelectionChangedCommand           { get; }


            public List<ClinicStaffModel>               ComboBoxMaterialPreparationProtocolsClinicStaffItemsSource
            {
                get { return _ComboBoxMaterialPreparationProtocolsClinicStaffItemsSource; }
                set
                {
                    _ComboBoxMaterialPreparationProtocolsClinicStaffItemsSource = value;
                    Raise(nameof(ComboBoxMaterialPreparationProtocolsClinicStaffItemsSource));

                        Raise(nameof(ComboBoxMaterialPreparationProtocolsClinicStaffSelectedItem));
                }
            }

            public ClinicStaffModel                     ComboBoxMaterialPreparationProtocolsClinicStaffSelectedItem
            {
                get { return Item.ClinicStaff != null ? Item.ClinicStaff : null; }
                set
                {
                    Item.ClinicStaff = value;
                    Raise(nameof(ComboBoxMaterialPreparationProtocolsClinicStaffSelectedItem));
                    
                        Raise(nameof(TextBoxMaterialPreparationProtocolsTimeShiftText));
                }
            }

Ich hab aktuell das Problem beim Laden meiner Eigenschaften das meine ClinicStaffItemsSource befüllt wurde, aber mein SelectedItem nicht richtig ausgewählt oder angezeigt wird.
private Nachricht | Beiträge des Benutzers
KroaX
myCSharp.de - Member

Avatar #avatar-4080.jpg


Dabei seit:
Beiträge: 315
Herkunft: Köln

beantworten | zitieren | melden

Zitat
Ich hab aktuell das Problem beim Laden meiner Eigenschaften das meine ClinicStaffItemsSource befüllt wurde, aber mein SelectedItem nicht richtig ausgewählt oder angezeigt wird.

Was heißt denn "richtig" ?
Zitat
Item.ClinicStaff = value;

Was ist diese "Item" ?

Und was hast du überhaupt bisher versucht und wobei kommst du nicht weiter?
private Nachricht | Beiträge des Benutzers
pinki
myCSharp.de - Member

Avatar #avatar-4072.jpg


Dabei seit:
Beiträge: 695
Herkunft: OWL

beantworten | zitieren | melden

Ist Item.Clinic Teil von ComboBoxMaterialPreparationProtocolsClinicItemsSource?


Statt

get { return Item.Clinic != null ? Item.Clinic : null; }
kannst du auch

get { return Item.Clinic; }
schreiben.
private Nachricht | Beiträge des Benutzers
ThomasE.
myCSharp.de - Member



Dabei seit:
Beiträge: 453

beantworten | zitieren | melden

Zitat von _Cashisclay


            public List<ClinicStaffModel> ComboBoxMaterialPreparationProtocolsClinicStaffItemsSource
            {
                get { return _ComboBoxMaterialPreparationProtocolsClinicStaffItemsSource; }
                set
                {
                    _ComboBoxMaterialPreparationProtocolsClinicStaffItemsSource = value;
                    Raise(nameof(ComboBoxMaterialPreparationProtocolsClinicStaffItemsSource));
                    Raise(nameof(ComboBoxMaterialPreparationProtocolsClinicStaffSelectedItem));
                }
            }
 

Liegt es vielleicht daran, daß du als ItemsSource z.Bsp. keine 'ObservableCollection' anstatt 'List' verwendest?
Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen...
private Nachricht | Beiträge des Benutzers
_Cashisclay
myCSharp.de - Member



Dabei seit:
Beiträge: 279

Themenstarter:

beantworten | zitieren | melden

Nicht richtig heißt das diese Property mir angezeigt wird :
<TextBox    Grid.Column="1"
                                                IsReadOnly="True"
                                                    HorizontalContentAlignment="Center" VerticalContentAlignment="Center"
                                                        Opacity="0.5"
                                                            Text="{Binding MaterialPreparationOfProtocols.ComboBoxMaterialPreparationProtocolsClinicStaffSelectedItem.DateOfTraining, Mode=OneWay, StringFormat=dd.MM.yyyy, UpdateSourceTrigger=PropertyChanged}"
                                            Style="{StaticResource BaseTextBox}"/>

Mir aber mein SelectedItem in meiner ComboBox nicht ausgewählt wird.

Das Item entspricht meinem ObjectModel
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von _Cashisclay am .
private Nachricht | Beiträge des Benutzers
_Cashisclay
myCSharp.de - Member



Dabei seit:
Beiträge: 279

Themenstarter:

beantworten | zitieren | melden

Ja, ist es.

@ThomasE. - Hat keinen Unterschied gemacht.

Grüße

Moderationshinweis von Abt (20.05.2019 - 11:21:14):

Keine Full Quotes
[Hinweis] Wie poste ich richtig?

private Nachricht | Beiträge des Benutzers
_Cashisclay
myCSharp.de - Member



Dabei seit:
Beiträge: 279

Themenstarter:

beantworten | zitieren | melden

Also ich hab das Gefühl das es irgendwie daran liegt das die ItemsSource "später" geladen wird und das trotz Raise des SelectedItems es nicht ausreicht das die UI das Item auch setzt.
private Nachricht | Beiträge des Benutzers
pinki
myCSharp.de - Member

Avatar #avatar-4072.jpg


Dabei seit:
Beiträge: 695
Herkunft: OWL

beantworten | zitieren | melden

Jetzt wurde noch MaterialPreparationOfProtocols eingeführt.
Wie steckt das da überall mit drin?

Edit:
Hast du mal mit Snoop oder ähnlichem nachgesehen, ob das Binding denn auch gültig ist oder ob es da irgendwo einen Fehler gibt?
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von pinki am .
private Nachricht | Beiträge des Benutzers
_Cashisclay
myCSharp.de - Member



Dabei seit:
Beiträge: 279

Themenstarter:

beantworten | zitieren | melden

MaterialPreparationOfProtocols ist eigentlich nur das ViewModel nur steckt das noch in einer anderen Klasse mit drin vom Vorentwickler, hat darauf also keine Einwirkungen.

Nein, sagt mir persönlich auch nichts, also hab das noch nie versucht. Allerdings greift die TextBox ja korrekt auf den Datensatz zu. Und die ItemsSource ist auch befüllt und wird angezeigt.

Grüße
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15704
Herkunft: BW

beantworten | zitieren | melden

Wenn Du die korrekten Typen wie ObservableCollection verwendest, spielt die Ladezeit prinzipiell keine Rolle.
Es wird aktualisiert, sobald die Items in der Collection sind (bezogen auf die Binding Direction).

Was soll denn dieses Raise() sein? Ist das eine eigene Implementierung von OnPropertyChanged() ?

Sieht mir so aus, dass das Rad an der Stelle neu erfunden wird.
Evtl. hier ein Fehler, dass die UI nicht korrekt benachrichtigt wird?
private Nachricht | Beiträge des Benutzers
_Cashisclay
myCSharp.de - Member



Dabei seit:
Beiträge: 279

Themenstarter:

beantworten | zitieren | melden

        public virtual void Raise(string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

            if (IsTrackingChanges) _hasChanged = true;
        }

Es klappt ja auch mit anderen ComboBoxen nur mit dieser nicht, obwohl ich nichts anders mache, nur das die Daten erst zur Laufzeit geladen werden.
private Nachricht | Beiträge des Benutzers
KroaX
myCSharp.de - Member

Avatar #avatar-4080.jpg


Dabei seit:
Beiträge: 315
Herkunft: Köln

beantworten | zitieren | melden

Mir persönlich ist die ganze Geschichte etwas zu undurchsichtig beschrieben. Man sieht nicht wo / wann und wie du dein "Item" im Code setzt. Ich vermute das es damit zusammen hängt.

Dein Combobox Binding fehlt leider auch, denn wie du beschrieben hast scheint dein SelectedItem schon falsch zu sein?

Ich würde auch allgemein davon abraten im Xaml Vekettungen von Properties im Binding zu nutzen. Setz deinen Datacontext an deinem Steuerelement möglichst explizit so dass du maximal einen Punkt, besser aber gar keinen Punkt im Binding nutzen musst.
private Nachricht | Beiträge des Benutzers
mfe
myCSharp.de - Member



Dabei seit:
Beiträge: 180

beantworten | zitieren | melden

Setze einen Haltepunkt nach dem Laden der Oberfläche und gib den DataContext vom ComboBox Control aus. Hast du im Output irgendwelche Binding Errors?

Wahrscheinlich passt ein Binding nicht.

Das könnte vlt auch helfen https://get-the-solution.net/blog/ItemsSource%20zu%20UserControl%20hinzuf%C3%BCgen
private Nachricht | Beiträge des Benutzers
MarsStein
myCSharp.de - Experte

Avatar #avatar-3191.gif


Dabei seit:
Beiträge: 3429
Herkunft: Trier -> München

beantworten | zitieren | melden

Hallo,

bist Du ganz sicher, dass das SelectedItem, dass Du initial setzen willst, die selbe Instanz ist, die auch in der ItemsSource der ComboBox steckt?

Wenn Du das Item z.B. zweimal aus den selben Daten generierst, einmal für die Nutzung als SelectedItem und einmal für die Verwendung in der ItemsSource, dann hättest Du nicht die selbe Instanz und dann ergäbe sich genau Deine Fehlerbeschreibung.

Gruß, MarsStein
Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca
private Nachricht | Beiträge des Benutzers
ThomasE.
myCSharp.de - Member



Dabei seit:
Beiträge: 453

beantworten | zitieren | melden

Zitat von MarsStein
bist Du ganz sicher, dass das SelectedItem, dass Du initial setzen willst, die selbe Instanz ist, die auch in der ItemsSource der ComboBox steckt?

natürlich im Zusammenhang mit
Zitat von Abt
Wenn Du die korrekten Typen wie ObservableCollection verwendest, spielt die Ladezeit prinzipiell keine Rolle.
Es wird aktualisiert, sobald die Items in der Collection sind (bezogen auf die Binding Direction).

zudem auch gut zu wissen wie
Zitat von KroaX
… wo / wann und wie du dein "Item" im Code setzt. Ich vermute das es damit zusammen hängt.

um es mal zusammenzufassen.
Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen...
private Nachricht | Beiträge des Benutzers
_Cashisclay
myCSharp.de - Member



Dabei seit:
Beiträge: 279

Themenstarter:

beantworten | zitieren | melden

Zitat
bist Du ganz sicher, dass das SelectedItem, dass Du initial setzen willst, die selbe Instanz ist, die auch in der ItemsSource der ComboBox steckt?

Ja, bin ich. Hab es auch gerade nochmal geprüft.
Zitat
… wo / wann und wie du dein "Item" im Code setzt. Ich vermute das es damit zusammen hängt.

Im Konstruktor

<ComboBox   Grid.Column="1"
                                            Margin="4"
                                                ItemsSource="{Binding MaterialPreparationOfProtocols.ComboBoxMaterialPreparationProtocolsClinicStaffItemsSource, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                                    DisplayMemberPath="Name"
                                                        SelectedItem="{Binding MaterialPreparationOfProtocols.ComboBoxMaterialPreparationProtocolsClinicStaffSelectedItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
Dieser Beitrag wurde 3 mal editiert, zum letzten Mal von _Cashisclay am .
Attachments
private Nachricht | Beiträge des Benutzers
witte
myCSharp.de - Member



Dabei seit:
Beiträge: 966

beantworten | zitieren | melden

OK, dann rate ich auch einmal: wird die Collection im richtigen Thread aktualisiert? Läuft es im GUI-Context?
private Nachricht | Beiträge des Benutzers
pinki
myCSharp.de - Member

Avatar #avatar-4072.jpg


Dabei seit:
Beiträge: 695
Herkunft: OWL

beantworten | zitieren | melden

Ohne im Debugger sichtbare und übereinstimmende Object-ID könnten es immer noch nur gleiche Objekte sein.
private Nachricht | Beiträge des Benutzers
_Cashisclay
myCSharp.de - Member



Dabei seit:
Beiträge: 279

Themenstarter:

beantworten | zitieren | melden

Also das sind alle Daten die ich zu den Objekten im Debugger sehen kann, wenn ich noch irgendwas ergänzen kann oder noch irgendwo nachgucken kann, klär mich bitte auf.

Im Konstruktor werden die fehlenden Daten der ItemsSource geladen, das SelectedItem ist zu der Zeit schon bekannt, ich hatte ja immer gedacht daran liegt es, aber ihr meintet Ja der Eintrag wird gesetzt sobald die ItemsSource vorhanden ist.
private Nachricht | Beiträge des Benutzers
_Cashisclay
myCSharp.de - Member



Dabei seit:
Beiträge: 279

Themenstarter:

beantworten | zitieren | melden

Zitat


Ohne im Debugger sichtbare und übereinstimmende Object-ID könnten es immer noch nur gleiche Objekte sein.

Hm ...
Zitat
bist Du ganz sicher, dass das SelectedItem, dass Du initial setzen willst, die selbe Instanz ist, die auch in der ItemsSource der ComboBox steckt?



Ich hab gerade mal

ComboBoxMaterialPreparationProtocolsClinicStaffSelectedItem = ComboBoxMaterialPreparationProtocolsClinicStaffItemsSource.Where(x => x.Id == ComboBoxMaterialPreparationProtocolsClinicStaffSelectedItem.Id).SingleOrDefault();

als Zeile ergänzt .. Und der Eintrag wird jetzt angezeigt .. Ich würde mich gern in einem Loch vergraben. Wie kann es denn sein das ich ein Item anhand der ID aus der Datenbank vom gleichen Objekttyp Lade was 100% von den Werten zur ItemsSource gehört, nicht als Member anerkannt wird?

            public ClinicStaffModel                     ComboBoxMaterialPreparationProtocolsClinicStaffSelectedItem
            {
                get { return ComboBoxMaterialPreparationProtocolsClinicStaffItemsSource != null ? Item.ClinicStaff != null ? ComboBoxMaterialPreparationProtocolsClinicStaffItemsSource.Where(x => x.Id == Item.ClinicStaff.Id).SingleOrDefault() : null : null; }
                set
                {
                    Item.ClinicStaff = value;
                    Raise(nameof(ComboBoxMaterialPreparationProtocolsClinicStaffSelectedItem));
                    
                        Raise(nameof(TextBoxMaterialPreparationProtocolsTimeShiftText));
                }
            }

Das kann ja nicht die Lösung des Problems sein ..
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von _Cashisclay am .
private Nachricht | Beiträge des Benutzers
_Cashisclay
myCSharp.de - Member



Dabei seit:
Beiträge: 279

Themenstarter:

beantworten | zitieren | melden

Zitat
bist Du ganz sicher, dass das SelectedItem, dass Du initial setzen willst, die selbe Instanz ist, die auch in der ItemsSource der ComboBox steckt?

Tatsächlich lag hier der Hund begraben. Das SelectedItem war vom selben Typ wie die ItemsSource. Die Daten haben 1 & 1 übereingestimmt, trotzdem kann man ein geladenes Object aus der ItemsSource nicht damit vergleichen.

Meine Lösung sah nun so aus das ich in der Klasse von dem Typ der ItemsSource folgendes verändert habe :

        public override bool Equals(object obj)
        {

            if (obj == null || !(obj is ClinicStaffModel))
                return false;

            return ((ClinicStaffModel) obj).Id == this.Id;

        }

        public override int GetHashCode()
        {
            
            return Id.GetHashCode();

        }
private Nachricht | Beiträge des Benutzers
ThomasE.
myCSharp.de - Member



Dabei seit:
Beiträge: 453

beantworten | zitieren | melden

Zitat von _Cashisclay

        public override bool Equals(object obj)
        {
            ClinicStaffModel csm = obj as ClinicStaffModel;
            return csm != null ? csm.Id == this.Id : false;
        }

Etwas aufhübschen
Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen...
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15704
Herkunft: BW

beantworten | zitieren | melden

Zitat von ThomasE.
Etwas aufhübschen


Extremer aufhübschen:

  public override bool Equals(object obj) => obj is ClinicStaffModel csm && csm.Id == Id;
private Nachricht | Beiträge des Benutzers
_Cashisclay
myCSharp.de - Member



Dabei seit:
Beiträge: 279

Themenstarter:

beantworten | zitieren | melden

Danke fürs aufhübschen, aber kann die Lösung vielleicht noch jemand bestätigen aus eigener Erfahrung? :rtfm:
private Nachricht | Beiträge des Benutzers
KroaX
myCSharp.de - Member

Avatar #avatar-4080.jpg


Dabei seit:
Beiträge: 315
Herkunft: Köln

beantworten | zitieren | melden

Aus eigener Erfahrung kann ich sagen:

- Arbeite entweder mit denselben Objektinstanzen ( Sprich keine Notwendigkeit Equals zu überschreiben ). Dadurch hältst du dich auf jeden Fall daran deine Objektinstanzen anständig weiter zu reichen und zu verwerfen.

ODER

- Arbeite mit Objekt ID's ( Sprich DisplayMember + ValueMember ) -> ValueMember ist hier deine ID damit das Steuerelement selbst das passende Objekt aus der Itemssource holt anhand ihres values.

Einen Mix aus beidem kann ich nicht empfehlen. Die Frage die du dir auch stellen solltest. Warum hast du überhaupt 2x eine Instanz vom selben Objekt? Bzw. mit demselben Value. Und wenn ja woher kommt es. Du ignorierst dieses potentielle Problem grade.
private Nachricht | Beiträge des Benutzers
witte
myCSharp.de - Member



Dabei seit:
Beiträge: 966

beantworten | zitieren | melden

Zitat von KroaX
Warum hast du überhaupt 2x eine Instanz vom selben Objekt? Bzw. mit demselben Value. Und wenn ja woher kommt es.
Sowas passiert beispielsweise wenn der Client sich Objekte für eine ComboBox besorgt um eine 1:n-Beziehung abzubilden und am zu bearbeitenden Modellobjekt ein bereits ein solches Objekt hängt, was die ComboBox darstellen soll.
IEquatable<TModel> bzw Equals(TModel) zu überschreiben ist gefährlich wenn das Objekt gerade angefügt wurde, gespeichert wird und die ID sich ändert. (wenn der Client z.B. nicht mit einer GUID stempelt)
private Nachricht | Beiträge des Benutzers