Laden...

WPF: Öffnen eines neuen Windows

Erstellt von Madleen vor 9 Jahren Letzter Beitrag vor 9 Jahren 3.870 Views
M
Madleen Themenstarter:in
35 Beiträge seit 2014
vor 9 Jahren
WPF: Öffnen eines neuen Windows

Hallo!
Ich habe es nun endliche(jedenfalls beinahe) geschafft mein anfängliches Projekt nach dem MVVM prinzip neu zu schreiben.
Mir fehlt nurnoch das Wissen wie ich ein neues Fenster öffne, dann ist es endlich vollbracht.

So, nun das eigentliche Problem:
Da das ViewModel ja nichts von der View weiss, hab ich irgendwie keine Ahnung wie ich das machen soll?!
Ich hab momentan ein ExcecuteSearchWindowcommand, in dem ich das andere Fenster (das lediglich ein paar Sucheinstellungen für den Nutzer bereitstellt, sollte ich dennoch dafür ein neues ViewModel anlegen?) halt aufrufen wollen würde.

Über Google bin ich auf ein paar wenige Beispiele gestossen, die aber beinahe immer davon ausgehen das ViewModel und View im selben Projekt sind?!
Und die anderen die ich fand waren hunderte Zeilen lang, da hab ich nicht so recht durchgeblickt.

Gibt es da eine "relativ" simple und vorallem verständliche Art dies zu machen?

Also quasi, wenn ich auf meine Menueleiste klicke und mein command ausgeführt wird, dass dann das andere Fenster aufploppt.

Grüße und danke schonmal

2.207 Beiträge seit 2011
vor 9 Jahren

Hallo Madleen,

du kannst ein Command machen und dann einfach dein Window erstellen, DataContext zuweisen, wenns eins braucht und anzeigen lassen mit

myWindow.Show();

Gruss

Coffeebean

692 Beiträge seit 2008
vor 9 Jahren

Hi,

also ich mache das auch so, bzw. ähnlich. Ich löse im Command ein Event aus, auf das die GUI z.B. dein MainWindow hört und beim auslösen das Fenster anlegt und anzeigt.
Denn sonst müsste ja ein Model eine view anlegen... Dies gefällt mir persönlich nicht.

Schöne Grüße
Quaneu

M
Madleen Themenstarter:in
35 Beiträge seit 2014
vor 9 Jahren

Hi,
das Problem dabei ist ja, das die View im Viewmodel nicht bekannt ist?!
Darum kann ich mir ja keine Instanz von dem Fenster holen?
Oder hab ich da was falsch verstanden?
Weil so wollte ich es ja auch eigentlich machen, bzw. so hab ich es vorher gemacht:

  public void auswahl_click(object sender, RoutedEventArgs e)
        {
            Einstellungen suchwindow = new Einstellungen();
            app_config_load(suchwindow);
            suchwindow.Show();
            
        }

was ja nichtmehr funktioniert.

nun hab ich mein:

   private ICommand searchwindowcommand;

       public ICommand SearchWindowCommand
       {
           get
           {
               if (searchwindowcommand == null)
               {
                   searchwindowcommand = new RelayCommand(p => ExcecuteSearchwindowcommand());
               }
               return searchwindowcommand;
           }
       }

       public void ExcecuteSearchwindowcommand()
       {
           
       }
         
    }

und hab kA was jetzt zu tun ist 😭

Vielleicht hab ich euch aber auch nur falsch verstanden?! 😃

Leider kann ich erst morgen früh wieder reinschauen.
Bis morgen !

692 Beiträge seit 2008
vor 9 Jahren

Deine View hat doch das ViewModel als DataContext. Somit könntest Du doch in der View das Event deines ViewModels abonnieren und darauf hören. Somit muss deine View das ViewModel nicht kennen.

4.931 Beiträge seit 2008
vor 9 Jahren

Hallo Madleen,

neben Views und ViewModels werden bei WPF (bzzw. dem MVVM-Pattern) häufig auch noch Service-Klassen verwendet, welche nicht direkt mit einem View in Verbindung stehen. Und dies wäre so ein Fall für eine DialogService-Klasse, s. z.B. Showing Dialogs When Using the MVVM Pattern

Dein Einstellungen-View würde sich dann bei dem DialogService registrieren und das andere ViewModel ruft dann über den (injizierten) DialogService dann diese View auf (im Artikel sind zwei verschiedene Vorgehensweisen beschrieben).

2.207 Beiträge seit 2011
vor 9 Jahren

Hallo Madleen,

Hast du deine Commands im ViewModel? Wenn ja: Mach deine Commands in einen eigenen Namespace. Das sind eigene Klassen und leiten von ICommand ab. Das ist viel sauberer. Dazu den von TH69 geposteten Link mit dem Service und dann hast du eine gute Lösung.


public class MyCommand : ICommand
{
   //Execute und CanExecute
}

und das bietest du dann über das ViewModel an. Sonst wird dein VM riesig und sehr unübersichtlich.

Gruss

Coffeebean

F
10.010 Beiträge seit 2004
vor 9 Jahren

Naja, wenn man eines der vielen MVVM Frameworks benutzt, die einem vieles abnehmen und zudem gut getestet sind, ist es z.b. bei Caliburn.Micro Caliburn Micro Part 5: The Window Manager

M
Madleen Themenstarter:in
35 Beiträge seit 2014
vor 9 Jahren

@Coffebean
Okay, klingt sinnig. Ich dachte eigentlich das dies auch zum ViewModel gehört.
Das werde ich mal gleich machen 😃

Und danke für die vielen Tipps. Ich werd mir mal die Links anschauen und schauen was passiert.

Ich werde dann berichten ob es mir geholfen hat.

2.207 Beiträge seit 2011
vor 9 Jahren

Hallo Madleen,

das ViewModel dient zwar zum Binden von Daten, ist aber im Prinzip nur eine Fassade für das, was darunter arbeitet. Da können Services drunter sein, Commands, InfoProvider etc.

Im Binding muss man ja nicht auf gleich das erste Property binden. Man kann sich ja an Properties "langhangeln".

So ist man in der Lage die einzelnen Zuständigkeiten zu trennen bzw. getrennt zu halten ohne im VM was zu "vermischen".

Gruss

Coffeebean

M
Madleen Themenstarter:in
35 Beiträge seit 2014
vor 9 Jahren

Hey Th69,
ich hab mich mal an dem Artikel versucht, aber ich muss ehrlich zugeben, das ich den Artikel kaum verstehe und er mir daher nicht wirklich weiterhilft 😭
Ich kann überhaupt nicht nachvollziehen (da mein wissen doch noch etwas zu gering für solch komplexe sachen ist) was da passiert in den Klassen bzw. dem Interface und allgemein wo dinge wie:
IFolderBrowserDialog oder IWindowViewModelMappings herkommen und so.

Hach, ist das frustrierend wenn eigentlich alles fertig ist und es an sowas harpert.
Ich hätte auch nicht gedacht das es so umständlich ist ein anderes Fenster zu öffnen?!
Also falls da noch wer ein paar gescheite hilfestellungen hat, ich freue mich darüber 😃
Besser als Stumpf alles mögliche zu versuchen und immer dran zu scheitern.

Übrigens, wie meint dud as mit "Event abonomieren"? @Quaneu
Irgendwie finde ich dazu nichts.
Weil das klingt für mich irgendwie am verständlichsten 😃

Und @FZelle auf die Seite bin ich auch schon gestoßen. Das Problem dabei ist, das ich dann mein gesamtes Projekt nochmal umarbeiten müsste 😭
Aber sicherlich für die nächste Anwendung dann interessant.

@Coffeebean
Wie "hangelt" man sich denn an propertys lang? Klingt irgendwie ziemlich wichtig wenn man mal größere Anwendungen hat.

2.207 Beiträge seit 2011
vor 9 Jahren
myWindow.Show();  

Im command aufrufen. Woran scheitert es denn?

Gruss

Coffeebean

M
Madleen Themenstarter:in
35 Beiträge seit 2014
vor 9 Jahren

Huhuuuu,
mhm , ganz einfach daran, das ich so ja das Fenster nicht aufrufen kann 😦

Also das Projekt sieht ja wie folgt aus:

DBSchicht --> Klassenbibliothek mit den ganzen Abfragen
Model --> MIt den dazugehörigen Klassen
Startapplikation
View --> 2 Views drinne, einmal das Hauptfenster und dann das andere Fenster, das beim Klick geöffnet werden soll
Viewmodel --> Klassenbibliothek mit dem Viewmodel
Und halt die ViewModelBase

Das ViewModel weiss ja nichts über die View und so, drum kann ich ja nicht window.show() verwenden?

Daher dann wohl auch immer diese riiiiesen Beispiele die ich halt nicht nachvollziehen kann, scheinbar weils ja nicht einfach so geht 😦

Verstehst du was ich meine?
Und danke, das du dir soviel Zeit nimmst.

W
955 Beiträge seit 2010
vor 9 Jahren

Hallo,

wenn Du häufiger WPF-Apps erstellst, kann ich Dir nur FZelles Rat empfehlen. Nimm ein MVVM-Framework wie Caliburn oder WAF. Diese Teile bieten Dir so etwas mit Hilfe von Services/Interfaces/Dependency Injection an. Das sollte schneller gehen als tagelang hier selber was zu stricken oder rumzufragen.

692 Beiträge seit 2008
vor 9 Jahren

Also ich mache das so. Der Nachteil ist, man hat ein bisschen "Code behind"...

Das Model:


public event EventHandler ShowWindowEvent;

#region Commands
public RelayCommand ShowWindowCommand { get; private set; }
#endregion

#region Command Methods
private void ShowWindow(Object parameter)
{
   OnShowWindow();
}
#endregion

private void OnShowWindow()
{
	EventHandler handler = this.ShowWindowEvent;
	if (handler != null)
	{
		handler(this, EventArgs.Empty);
	}
}

In der View das Event abonieren und


private void _model_ShowWindow(Object sender, EventArgs e)
{
    // Hier das Fentser anzeigen. Wenn Du das Model für das neue Fenster mit in die EventArgs packst, könntest Du diesen hier benutzen
}

Ist wohl nicht der sauberste Weg... lasse mich aber gern belehren 😃.

Schöne Grüße
Quaneu

4.931 Beiträge seit 2008
vor 9 Jahren

Hallo Madleen,

bei dem Artikel brauchst du eigentlich die Interna gar nicht verstehen, sondern nur die DialogService-Klasse zu deinem Projekt hinzufügen und dann anwenden.

2.207 Beiträge seit 2011
vor 9 Jahren

Hallo Madleen,

dann stimmt was mit deiner Architektur nicht. Die Viewmodels können schon "nah" bei der View liegen. Das ist nicht das Problem. Willst du eine saubere Trennung, lass die ViewModels einfach eine Fassade sein (hier beschrieben). Aber schliesslich müssen die ja zum binden herhalten. Somit brauchen die nicht in einer eigenen Lib zu sein. Ebenfalls die Commands. Die können wieder externe Services etc. aufrufen. Aber trotzdem werden sie ja übers VM angeboten. Also leg sie dahin, wo sie gebraucht werden: beim ViewModel (extra Namespace).

So sollte auch das öffnen von nem Fenster kein Problem sein. Schau dir trotzdem mal die geposteten Frameworks an. Die sind schon nicht schlecht.

Gruss

Coffeebean

M
Madleen Themenstarter:in
35 Beiträge seit 2014
vor 9 Jahren

Huhuuu Th69,
ich werd mich gleich nochmal dran versuchen.
Es hat mich halt abgeschreckt weil es so komplex war und ich nichts verstanden hab, aber naja, dann sehe ich das mal als Blackbox an 😃

@Coffebean
Ich hab mir zumindest mal dieses ominoese WAF angeschaut, aber irgendwie findet man dazu wirklich nur sehr spährlich informationen.
Naja, ich denke heute werde ich noch etwas Zeit haben mir dann Caliburn mal etwas näher betrachten.
Und okay, das wusste ich nicht.
Ich dachte das muss alles strikt und fein säuberlich in verschiedenen Projekten gelagert sein.
Ich werde mir nochmal den Link den du geposted hast durchlesen.

Danke euch schonmal, ich meld mich dann vermutlich später nochmal.

2.207 Beiträge seit 2011
vor 9 Jahren

Ich dachte das muss alles strikt und fein säuberlich in verschiedenen Projekten gelagert sein.

Das ist auch so. Zumindest sollte es so sein. Aber meine Aussage widerspricht deiner ja nicht. VM und View können ruhig in einem Projekt liegen. Alles, was darunter kommt, kann man dann aufteilen. Wie genau, das bestimmst jetzt du als Entwickler, Architekt etc. Die Diskussion führt aber hier zu weit.

In meinem Blogpost habe ich eine Möglichkeit zur Trennung beschrieben. Unter/Hinter dem ViewModel bist du ja dann frei.

Gruss

Coffeebean