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
Object von Window zu Window weiter geben
Kriz
myCSharp.de - Member



Dabei seit:
Beiträge: 81

Themenstarter:

Object von Window zu Window weiter geben

beantworten | zitieren | melden

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
private Nachricht | Beiträge des Benutzers
Taipi88
myCSharp.de - Member

Avatar #avatar-3220.jpg


Dabei seit:
Beiträge: 1044
Herkunft: Mainz

beantworten | zitieren | melden

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
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15618
Herkunft: BW

beantworten | zitieren | melden

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
private Nachricht | Beiträge des Benutzers
Kriz
myCSharp.de - Member



Dabei seit:
Beiträge: 81

Themenstarter:

beantworten | zitieren | melden

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???
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Kriz am .
private Nachricht | Beiträge des Benutzers
ThomasE.
myCSharp.de - Member



Dabei seit:
Beiträge: 453

beantworten | zitieren | melden

Zitat von Kriz
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...
private Nachricht | Beiträge des Benutzers
Kriz
myCSharp.de - Member



Dabei seit:
Beiträge: 81

Themenstarter:

beantworten | zitieren | melden

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();
    }
private Nachricht | Beiträge des Benutzers
Kriz
myCSharp.de - Member



Dabei seit:
Beiträge: 81

Themenstarter:

beantworten | zitieren | melden

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!
private Nachricht | Beiträge des Benutzers
ThomasE.
myCSharp.de - Member



Dabei seit:
Beiträge: 453

beantworten | zitieren | melden

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
Zitat
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...
private Nachricht | Beiträge des Benutzers
Kriz
myCSharp.de - Member



Dabei seit:
Beiträge: 81

Themenstarter:

beantworten | zitieren | melden

Zitat
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 :)
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,
Zitat
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
private Nachricht | Beiträge des Benutzers
ThomasE.
myCSharp.de - Member



Dabei seit:
Beiträge: 453

beantworten | zitieren | melden

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...
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 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
private Nachricht | Beiträge des Benutzers
ThomasE.
myCSharp.de - Member



Dabei seit:
Beiträge: 453

beantworten | zitieren | melden

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

Hall,
Zitat von ThomasE.
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.
Zitat von ThomasE.
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.
Zitat von ThomasE.
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
private Nachricht | Beiträge des Benutzers
ThomasE.
myCSharp.de - Member



Dabei seit:
Beiträge: 453

beantworten | zitieren | melden

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...
private Nachricht | Beiträge des Benutzers