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
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ß
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.
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" ?
Item.ClinicStaff = value;
Was ist diese "Item" ?
Und was hast du überhaupt bisher versucht und wobei kommst du nicht weiter?
Ist Item.Clinic
Teil von ComboBoxMaterialPreparationProtocolsClinicItemsSource
?
Statt
get { return Item.Clinic != null ? Item.Clinic : null; }
kannst du auch
get { return Item.Clinic; }
schreiben.
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... 😄
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
Ja, ist es.
@ThomasE. - Hat keinen Unterschied gemacht.
Grüße
Keine Full Quotes
[Hinweis] Wie poste ich richtig?
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.
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?
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
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?
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
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.
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.
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
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
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
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
… 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... 😄
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.
… 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}"/>
OK, dann rate ich auch einmal: wird die Collection im richtigen Thread aktualisiert? Läuft es im GUI-Context?
Ohne im Debugger sichtbare und übereinstimmende Object-ID könnten es immer noch nur gleiche Objekte sein.
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.
Ohne im Debugger sichtbare und übereinstimmende Object-ID könnten es immer noch nur gleiche Objekte sein.
Hm ...
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 ..
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();
}
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... 😄
Etwas aufhübschen 😉
Extremer aufhübschen:
public override bool Equals(object obj) => obj is ClinicStaffModel csm && csm.Id == Id;
😉
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Danke fürs aufhübschen, aber kann die Lösung vielleicht noch jemand bestätigen aus eigener Erfahrung? :rtfm: 🙂
Aus eigener Erfahrung kann ich sagen:
ODER
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.
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)