Laden...

Object von Window zu Window weiter geben

Erstellt von Kriz vor 6 Jahren Letzter Beitrag vor 6 Jahren 2.870 Views
K
Kriz Themenstarter:in
141 Beiträge seit 2017
vor 6 Jahren
Object von Window zu Window weiter geben

Hi zusammen,

sicher ganz einfach, aber ich komm da gerade nicht weiter:

Ich habe ein UserControl sammt ViewModel. Dieses ViewModel besitzt die Property "SelectedObject". Von diesem ViewModel aus wird ein Window geöffnet, auch wieder mit ViewModel, in dem das "SelectedObject" bearbeitet wird (Eigeneschaften wie Name, ID, usw). Bis hier hin klappt es auch.
Nun möchte ich das geänderte Object wieder an das erste UserControl zurück geben, aber da steh ich auf dem Schlauch, wie bekomme ich das am besten hin?
Versucht hatte ich schon das SelectedObject als Referenz zu übergeben, allerdings meckert VS dass Eigenschaften nicht mit "ref" übergeben werden können.
Zweiter Gedankenansatz war das Window in dem das SelectedObject bearbeitet wird als Dialog zu entwerfen und das SelectedObject quasi als DialogResult zurück zu geben, aber auch da weiss ich nicht weiter.

Hof eich konnte die Problematik erklären und mir kann jemand helfen.

Danke Euch!

Chris

1.029 Beiträge seit 2010
vor 6 Jahren

Hi,

grundsätzlich liest sich dein Post so, als ob das Objekt ohnehin ein Referenztyp ist - damit brauchst du kein "ref" - es ist und bleibt das selbe Objekt.

Abgesehen davon ist mir nicht ganz klar was du da zurückgeben musst bzw. wie es woher kommt, sodass das eigentliche Hauptfenster das Objekt nicht mehr kennt.

Grundsätzlich können beide UserControls mit dem selben "SelectedObject" arbeiten - und wenn INotifyPropertyChanged ordentlich implementiert - brauchst du da gar nichts zurückzugeben.

LG

16.806 Beiträge seit 2008
vor 6 Jahren

Schau Dir mal Reactive Extensions an.
Das ist genau für solche reaktiven Anforderungen gedacht - und sollte eigentlich in keiner UI Applikation mehr fehlen.
https://github.com/Reactive-Extensions/Rx.NET

K
Kriz Themenstarter:in
141 Beiträge seit 2017
vor 6 Jahren

Ich verzweifel...

erstmal Danke Taipi88, es stimmt dass das Objekt ein Referenzobjekt ist und sich ein "ref" erübrigt.

also wie es scheint, wird das Objekt richtig von Window A zu Window B übergeben. In Window B kann ads SelectedObject auch bearbeitet werden und die neuen Informationen werden auch in Window A angezeigt.
Im Window B habe ich eine Combobox mit einer ListOfSelectedObject, die per SelectedItem als SelectedObject gebunden sind. Wenn ich nun aus der Liste ein anderes SelectedObject auswähle, wird das nicht übernommen, im Window A wird weiterin das ursprüngliche SelectedObject angezeigt.
Also wenn ich das SelectedObject bearbeite, Name, Id, oder sontiges, wird das korrekt übernommen, aber wenn ich dem SelectedObject ein neues Objekt zuweisen will, dann wird es ignorieret...

Was mache ich falsch???

T
461 Beiträge seit 2013
vor 6 Jahren

aber wenn ich dem SelectedObject ein neues Objekt zuweisen will, dann wird es ignorieret...

Dann stellt sich die Frage:
.) Wird das neue Object tatsächlich im Window am Property übernommen? (Debuggen)
.) Wenn ja, wird(werden) die Bindung(en) nach der Änderung nicht aktualisiert?

Grüße

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... 😄

K
Kriz Themenstarter:in
141 Beiträge seit 2017
vor 6 Jahren

Hier mal noch ein paar Code-Snippets, vllt hilfts bei der Kärung...

User-Control-XAML:

<Label Content="{Binding Path=SelectedSchedule.Name}" Margin="0,-6,0,0" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="20" Height="32" Width="87"/>

User-Control-ViewModel

 private Schedule mSelectedSchedule;

    public Schedule SelectedSchedule
    {
        get { return mSelectedSchedule; }
        set
        {
            mSelectedSchedule = value;
            OnPropertyChanged("SelectedSchedule");
        }
    }

    public EmployeeWeekCheckButon_VM(Schedule GivenSchedule)
    {
        SelectedSchedule = GivenSchedule;
    }

    private void Edit()
    {
        Forms.Tracking.View.frmEditTracking newForm = new Forms.Tracking.View.frmEditTracking(SelectedSchedule);
        newForm.ShowDialog();
        OnPropertyChanged("SelectedSchedule");
    }

    private void Delete()
    {
        SelectedSchedule = null;
    }

Edit-Window-XAML:

<ComboBox ItemsSource="{Binding ListOfSchedule}" SelectedItem="{Binding SelectedSchedule}" x:Name="cmdSchedule" HorizontalAlignment="Left" FontSize="16" Margin="17,27,0,0" VerticalAlignment="Top" Width="120"/>

Edit-Window-ViewModel:

private Schedule _SelectedSchedule;

    public Schedule SelectedSchedule
    {
        get { return _SelectedSchedule; }
        set { _SelectedSchedule = value;
            OnPropertyChanged("SelectedSchedule"); }
    }

    private ObservableCollection<object> _ListOfSchedule;

    public ObservableCollection<object> ListOfSchedule
    {
        get { return _ListOfSchedule; }
        set { _ListOfSchedule = value;
            OnPropertyChanged("ListOfSchedule");
        }
    }

    public frmEditTracking_VM(Schedule GivenSchedule)
    {
        SelectedSchedule = GivenSchedule;
    }

    private void SaveAndClose()
    {
        SelectedSchedule.isTracked = true;
        OnClosingRequest();
    }
K
Kriz Themenstarter:in
141 Beiträge seit 2017
vor 6 Jahren

StackOverflow sei dank, Problem gelöst!

Falls jemand mal vor dem gleichen Problem steht: Die Lösung ist das ganze ViewModel als Parameter an das neue Window zu geben, nicht nur das eine Objekt, dann wird auch ein neu erstelltes Objekt übernommen.

Trotzdem Danke!

T
461 Beiträge seit 2013
vor 6 Jahren

Hallo,

tut mir leid, aus deinem Code und Beschreibungen werd ich nicht schlau, mag auch sein, daß ich grad den Kopf mit was anderem voll habe...
--> etwas passt hier nicht zusammen

Falls jemand mal vor dem gleichen Problem steht: Die Lösung ist das ganze ViewModel als Parameter an das neue Window zu geben, nicht nur das eine Objekt, dann wird auch ein neu erstelltes Objekt übernommen.

Ich kann mir nicht vorstellen das das die Lösung des Problems ist? Wenn man anstatt des Objekts das ViewModel übergibt... Bricht das nicht das MVVM?

Zudem:


    private ObservableCollection<object> _ListOfSchedule;

    public ObservableCollection<object> ListOfSchedule
    {
        get { return _ListOfSchedule; }
        set { _ListOfSchedule = value;
            OnPropertyChanged("ListOfSchedule");
        }
    }

warum 'object' ? Gibt es keinen Typen dazu?

Grüße

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... 😄

K
Kriz Themenstarter:in
141 Beiträge seit 2017
vor 6 Jahren

warum 'object' ? Gibt es keinen Typen dazu?

Weil die ObservableCollection mit einer Datenbankabfrage gefüttert wird die viele verschiedene Typen abfragen kann/soll, da fand ich es am einfachsten mit "object" zu arbeiten.

Ich fad für die Problematik leider keinen anderen Lösungsansatz, da zwar das Objekt bearbeitet werden konnte und die Änderungen auch im Urpsrung, also UserControl, korrekt angezeigt wurden, sobald ich aber dem Objekt ein neues zuweisen wollte, wurde nichts übernommen. So funktioniert es nun.

Wenn es eine einfachere, bzw MVVM-passendere Lösung gibt, dann her damit 😃

3.170 Beiträge seit 2006
vor 6 Jahren

Hallo,

Bricht das nicht das MVVM?

Nein, warum?
Man benutzt ein und dasselbe ViewModel um es in 2 verschiedenen Views (hier: einem UserControl und einem Window) anzuzeigen.
Was sollte da das MVVM brechen?

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

T
461 Beiträge seit 2013
vor 6 Jahren

Weil nicht die Daten sondern das ViewModel hin und her verschoben werden....

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... 😄

3.170 Beiträge seit 2006
vor 6 Jahren

Hallo ThomasE.,

ja - und? Ich sehe ehrlich gesagt den Punkt nicht.
wenn ich dieselben Daten in mehreren Views anzeigen will, und habe dafür schon ein ViewModel, dann kann ich es doch auch benutzen.
Genau genommen wird das ViewModel ja nicht hin und her verschoben, sondern einfach einer weiteren View bekanntgemacht.

Stell DIr vor Du hast eine ListView, in der Du Daten einzeilig in Kurzform anzeigst, und einen Bereich, in dem Du das selektierte Item bearbeiten kannst (also klassisch Master-Detail).
Dazu hast Du für gewöhnlich an die ListView eine ObservableCollection<ItemVM> gebunden, und das selektierte Item wird an beiden Stellen angezeigt.
Nun lagerst Du die Detail-View in ein separates Fenster aus. Und deshalb musst Du jetzt dem neuen Fenster das Model geben, woraus ein neues VM erzeugt wird, statt wie bisher einfach das gleiche VM zu benutzen?
Das macht die Sache unnötigerweise ganz schön kompliziert, vor allem die Synchronisation der Anzeige. Also wozu das Ganze?

Wenn ich die gleichen Daten in mehreren Views brauche, verwende ich auch wenn es geht dasselbe VM, wenn es sich für beide Views eignet. Und zwar unabhängig davon, ob das nun in einem anderen Fenster oder im Gleichen ist.

Die Erzeugung des Fensters im VM ist hier IMO viel eher etwas, was gegen MVVM verstößt, da das ViewModel hier die View (das neue Fenster) kennen muss, um es anzuzeigen. Das könnte man anders lösen, so dass das VM keine Ahnung von irgendwelchen Views haben muss.

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

T
461 Beiträge seit 2013
vor 6 Jahren

Hallo MarsStein,

ja, womöglich hab ich zu viel in Richtung Speicherauslastung gedacht, obwohl es in den meisten Fällen unnötig ist... 😉

Ich hatte es oft so gelöst, daß es ein VM gibt, in dem die Daten mitgeteilt werden.
Ich teilte meist die VM's in 2 Kategorien, nur schauen und bearbeiten können.

Nur schauen benötigt meist viel weniger Aufwand eine VM zu erstellen als eben bearbeiten können. Kommt sicher dadurch zustande 😃 und wenn man sich mal daran gewöhnt hat, denkt man manchmal gar nicht mehr so darüber nach...

Kann mir durchaus vorstellen, daß das mit dem VM's teilweise in meinen Fällen sehr praktisch gewesen wäre, das stimmt...

Die Erzeugung des Fensters im VM ist hier IMO viel eher etwas, was gegen MVVM verstößt, da das ViewModel hier die View (das neue Fenster) kennen muss, um es anzuzeigen. Das könnte man anders lösen, so dass das VM keine Ahnung von irgendwelchen Views haben muss.

Also da hätte ich gerne ein einfaches Beispiel, denn ich habe bisher keine für mich zufriedenstellende Lösung gefunden, vielleicht bin ich auch zu penibel 😉

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... 😄

3.170 Beiträge seit 2006
vor 6 Jahren

Hall,

Ich teilte meist die VM's in 2 Kategorien, nur schauen und bearbeiten können.

Was ja je nach Art und Anzahl der Daten auch völlig in Ordung und richtig ist - ich würde das halt nur nicht pauschalisieren.

Kann mir durchaus vorstellen, daß das mit dem VM's teilweise in meinen Fällen sehr praktisch gewesen wäre, das stimmt...

Eben - bei kleinen Datensätzen in einer überschaubaren Anzahl kann man's halt gerne auch anders machen.
Das wiederspricht aber deshalb nicht MVVM.

Also da hätte ich gerne ein einfaches Beispiel, denn ich habe bisher keine für mich zufriedenstellende Lösung gefunden, vielleicht bin ich auch zu penibel 😉

Naja, ehrlich gesagt nehme ich das auch nicht immer so ganz genau. Es geht aber schon.
Im Prinzip ist die Art, wie die Daten angezeigt werden, Logik der View. Meistens kann man sowas ja einfach über geeignete Bindings, DataTemplates etc. steuern. Nur wenn ein neues Fenster aufgemacht wird, klappt das eben nicht mehr so richtig.
Da kann man jetzt verschiedene Ansätze verfolgen:*Man kann sich direkt im Code behind an Events aus der View - also irgendwelcher Controls - hängen.
Und bevor mich jetzt jemand für diese Aussage steinigt: Ich bin durchaus der Auffassung, dass es sich dabei, die Art der Anzeige zu realisieren, um View-Logik handelt und dort implementiert werden darf.

*Man kann aber auch ganz normal mit Commands im VM arbeiten, und von dort aus ein eigenes Event (in dem konkreten Fall z.B. ein "EditRequested" feuern, das man entsprechend in der View abonniert.
Auch dabei wird man das im Code behind tun müssen, hat aber den Vorteil, dass man im VM bei Bedarf noch zusätzliche Logik ausführen kann.

*Bei größeren oder verschachtelten Projekten, wo man das gleiche Fenster von mehreren Stellen her öffnen möchte, kann man aber auch eine Art ViewManager nutzen, den man vom ViewModel aus (als Interface) aufruft und der sich dann darum kümmert, dass das richtige Fenster aufgeht. Dann hat man das auch vom ViewModel sauber getrennt. *Oder man verpasst den Fenstern noch ein passendes Interface und lässt sie sich ganz banal von einem DI-Container auflösen - was wiederum ziemlich nah an den vorher erwähnten ViewManager rankommt.

Hat alles so seine Pro und Contra, und ich weiss nicht, ob man da eine pauschale Empfehlung geben kann. Da muss man sich wirklich den Einzelfall anschauen. Aber möglich ist es allemal.

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

T
461 Beiträge seit 2013
vor 6 Jahren

Hallo,

danke für dene Meinungen.

Das mit den Fenstern habe ich eher so nach Punkt 3 von dir beschrieben umgesetzt, also doch eher in die richtige Richtung 😉

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... 😄