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
WPF: Öffnen eines neuen Windows
Madleen
myCSharp.de - Member



Dabei seit:
Beiträge: 36

Themenstarter:

WPF: Öffnen eines neuen Windows

beantworten | zitieren | melden

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

Avatar #avatar-3295.gif


Dabei seit:
Beiträge: 2459
Herkunft: Deutschland/Schweiz

beantworten | zitieren | melden

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

Avatar #avatar-3126.jpg


Dabei seit:
Beiträge: 688
Herkunft: Regensburg

beantworten | zitieren | melden

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



Dabei seit:
Beiträge: 36

Themenstarter:

beantworten | zitieren | melden

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

Avatar #avatar-3126.jpg


Dabei seit:
Beiträge: 688
Herkunft: Regensburg

beantworten | zitieren | melden

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

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4001

beantworten | zitieren | melden

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

Avatar #avatar-3295.gif


Dabei seit:
Beiträge: 2459
Herkunft: Deutschland/Schweiz

beantworten | zitieren | melden

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



Dabei seit:
Beiträge: 10072

beantworten | zitieren | melden

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



Dabei seit:
Beiträge: 36

Themenstarter:

beantworten | zitieren | melden

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

Avatar #avatar-3295.gif


Dabei seit:
Beiträge: 2459
Herkunft: Deutschland/Schweiz

beantworten | zitieren | melden

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



Dabei seit:
Beiträge: 36

Themenstarter:

beantworten | zitieren | melden

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

Avatar #avatar-3295.gif


Dabei seit:
Beiträge: 2459
Herkunft: Deutschland/Schweiz

beantworten | zitieren | melden

Zitat von Coffeebean

myWindow.Show();

Im command aufrufen. Woran scheitert es denn?

Gruss

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



Dabei seit:
Beiträge: 36

Themenstarter:

beantworten | zitieren | melden

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



Dabei seit:
Beiträge: 966

beantworten | zitieren | melden

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

Avatar #avatar-3126.jpg


Dabei seit:
Beiträge: 688
Herkunft: Regensburg

beantworten | zitieren | melden

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

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4001

beantworten | zitieren | melden

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

Avatar #avatar-3295.gif


Dabei seit:
Beiträge: 2459
Herkunft: Deutschland/Schweiz

beantworten | zitieren | melden

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



Dabei seit:
Beiträge: 36

Themenstarter:

beantworten | zitieren | melden

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

Avatar #avatar-3295.gif


Dabei seit:
Beiträge: 2459
Herkunft: Deutschland/Schweiz

beantworten | zitieren | melden

Zitat von Madleen
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
private Nachricht | Beiträge des Benutzers