MVVM - Funktion beim Start ausführen

  • WPF

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von fichz.

    MVVM - Funktion beim Start ausführen

    yo Leute,

    ich bin letztens über ein kleines Problem gestoßen welches ich nicht lösen konnte.
    Ich wollte eine WPF Anwendung mit dem MVVM Pattern erstellen, welche sich im Prinzip so verhaltet wie eine Konsolenanwendung, nur dass ich halt grafisch den Fortschritt anzeigen kann.

    Ziel der Anwendung ist es, bestimmte Dateien eines Ordners zu scannen, zusammenzuführen und an ein spezielles Ziel zu kopieren. An sich also nichts Großes.
    Ich will mich möglichst an MVVM halten. Das würde im Prinzip heißen -> keinen Code in der Codebehind Datei des Mainviews.

    Die Klassen und das Erstellen des Viewmodels ist kein Problem. Auf folgende Probleme bin ich aber gestoßen:
    - Wie kann ich eine Funktion des ViewModels nach dem Programmstart ausführen (wie bei einer Konsolenanwendung halt die nach dem Start loslegt)?
    - Wie kann ich dem ViewModel Programmparameter (Command Line Args) übergeben (in dem Fall zB der Pfad wo die fertigen Dateien hinkopiert werden sollen)?
    - Wie kann ich das Programm, nach dem Ausführen der Funktion, korrekt beenden (auch halt wie einer Konsolenanwendung)?

    lg
    fichz
    ScheduleLib 0.0.1.0
    Kleine Lib zum Anlaufen von Code zu bestimmten Zeiten
    Also: MVVM ist eine gute Sache, heißt aber nicht, dass absolut alles darüber laufen muss.
    Events darfst Du trotzdem noch im Codebehind behandeln. Solltest Du trotzdem unbedingt darauf bestehen geht sowas bspw. mit System.Windows.Interactivity: nuget.org/packages/System.Windows.Interactivity.WPF/

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:

    fichz schrieb:


    - Wie kann ich eine Funktion des ViewModels nach dem Programmstart ausführen (wie bei einer Konsolenanwendung halt die nach dem Start loslegt)?
    Im Konstruktor des Viewmodels

    fichz schrieb:


    - Wie kann ich dem ViewModel Programmparameter (Command Line Args) übergeben (in dem Fall zB der Pfad wo die fertigen Dateien hinkopiert werden sollen)?
    Environment.GetCommandlineArgs

    fichz schrieb:


    - Wie kann ich das Programm, nach dem Ausführen der Funktion, korrekt beenden (auch halt wie einer Konsolenanwendung)?
    weiß nicht - vlt. System.Windows.Application.Shutdown() ?
    Danke mal für die Antworten:
    @Trade Ok Wenn dies guter Stil ist hab ich kein Problem damit das ins Codebehind zu packen.

    @ErfinderDesRades
    zu Punkt 1: Im Konstruktor funktioniert es prinzipiell schon, jedoch ist es dann irgendwie kompliziert wenn die auszuführende Funktion als async deklariert ist. Da tendiere ich eher zu dem Loaded Event wie @Trade es beschrieben hat.

    zu Punkt 2: Würde funktionieren. Die Frage ist ob dies die sauberste Lösung ist?

    zu Punkt 3: Hab ein bisschen recherchiert und eine Lösung wäre, das Window als Referenz im ViewModel zu halten und wenn die Funktion fertig ist, diese mit Window.Close() zu beenden. Auch hier dir Frage ob dies sauber wäre.

    Hier mal ein bisschen Code zur Veranschaulichung:
    Spoiler anzeigen

    XML-Quellcode

    1. <c:MetroWindow x:Class="MetroTest.MainWindow"
    2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4. xmlns:c="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
    5. xmlns:local="clr-namespace:MetroTest"
    6. Title="MainWindow" Height="350" Width="525"
    7. BorderThickness="1" BorderBrush="{DynamicResource AccentColorBrush}" Loaded="MetroWindow_Loaded"
    8. >
    9. <c:MetroWindow.DataContext>
    10. <local:MainWindowViewModel x:Name="vm" />
    11. </c:MetroWindow.DataContext>
    12. <StackPanel>
    13. <TextBlock Text="{Binding Text, Mode=TwoWay}" />
    14. </StackPanel>
    15. </c:MetroWindow>


    C#-Quellcode

    1. // View
    2. public partial class MainWindow : MetroWindow
    3. {
    4. public MainWindow()
    5. {
    6. InitializeComponent();
    7. }
    8. private async void MetroWindow_Loaded(object sender, RoutedEventArgs e)
    9. {
    10. var vm = this.DataContext as MainWindowViewModel;
    11. vm.Window = this;
    12. await vm.TestStart();
    13. }
    14. }
    15. // ViewModel
    16. using System;
    17. using System.Collections.ObjectModel;
    18. using System.Threading.Tasks;
    19. using System.Windows;
    20. using System.Windows.Data;
    21. namespace MetroTest
    22. {
    23. public class MainWindowViewModel : NotifyPropertyChangedBase
    24. {
    25. private Window window;
    26. public Window Window
    27. {
    28. get { return window; }
    29. set { window = value; }
    30. }
    31. private string text;
    32. public string Text
    33. {
    34. get { return text; }
    35. set
    36. {
    37. text = value;
    38. OnPropertyChanged();
    39. }
    40. }
    41. public MainWindowViewModel()
    42. {
    43. Text = "Leer";
    44. }
    45. public async Task TestStart()
    46. {
    47. await Perform();
    48. }
    49. private async Task Perform()
    50. {
    51. Text = "Start";
    52. await Task.Delay(2000);
    53. Text = "50%";
    54. await Task.Delay(2000);
    55. Text = "100%";
    56. await Task.Delay(2000);
    57. Text = Environment.GetCommandLineArgs()[1];
    58. await Task.Delay(2000);
    59. window.Close();
    60. }
    61. }
    62. }


    lg
    ScheduleLib 0.0.1.0
    Kleine Lib zum Anlaufen von Code zu bestimmten Zeiten
    Definiere "sauber"

    zu 1) ich würd ma sagen, im CodeBehind rumzuwerkeln für Sachen, die man auch im Viewmodel abhandeln kann ist unsauber.
    zu 2) tja, ist Environment.GetCommandlineArgs() sauber? Oder annersrum: Inwiefern ist es schmutzig?
    zu 3) im Viewmodel ein Window zu halten ist wohl nicht sauber. Aber hier was sauberes: Application.MainWindow.Close()
    Naja "sauber" meine ich halt, was die empfohlene Art und Weise ist etwas zu bewerkstelligen. Sei es Seitens Microsoft, Patterns, Guidelines, ...
    Ich denke wenn es bei einer Abarbeitung des "Loaded-Events" der View bleibt, sollte es nicht unsauber sein. Das mit dem Window ins Viewmodel laden gefällt mir auch nicht besonders, da im Prinzip eine Abhängigkeit entsteht welche nicht entstehen sollte.

    1) denke ist oben beschrieben
    2) Ein Vorteil der ja aus MVVM unter anderem besteht ist, dass man ViewModels Komponenten-Tests unterziehen kann. Dies würde mit Environment.GetCommandLineArgs() nicht mehr funktionieren (außer es gibt hierfür eine Möglichkeit)
    3) Diese Methode wird im ViewModel nicht erkannt. Es existiert aber die Methode Environment.Exit(int exitCode) welche auch das Programm beendet.

    lg
    ScheduleLib 0.0.1.0
    Kleine Lib zum Anlaufen von Code zu bestimmten Zeiten

    fichz schrieb:

    Naja "sauber" meine ich halt, was die empfohlene Art und Weise ist etwas zu bewerkstelligen. Sei es Seitens Microsoft, Patterns, Guidelines, .
    Hmm - da bin ich draussen.

    Ich verstehe unter "sauber" inhaltlich begründetes, nicht was iwelche anderen sagen.

    Bei mir hat "sauber" einige Kriterien (hab noch nie konzentriert drüber nachgedacht)
    • v.a. wie gewünscht funktionierend
    • möglichst einfach
    • möglichst verständlich
    • möglichst wenig Abhängigkeiten
    • möglichst vielseitig verwendbar
    • möglichst leicht wartbar
    • ...
    also es sind wie Dimensionen, die im Einzelfall einander auch mal widersprechen können. Und wenn dieselbe Anforderung auf verschiedene Weisen umgesetzt werden kann, dann ergibt sich meist eine der Alternativen als die beste, beurteilt nach diesen Kriterien (und was mir evtl. noch so einfällt). Ja, diese beste Lösung ist dann "sauber".
    Deswegen gibt es ja genau solche "Guidelines". Weil sich halt diese Variante bewährt hat. Es muss nicht zu 100% genau so sein, jedoch haben diese sich wahrscheinlich bewährt aus bestimmten Gründen. Und diese will ich eben so gut es geht einhalten. Ich hatte schon oft das "Problem" es dann auf eigene Faust zu machen und bin irgendwann dann an einem Punkt angelangt wo es dann nicht mehr funktioniert hat weil mich vielleicht "zu wenig" daran gehalten habe und es deswegen nun so ist wie es ist.

    Ich will einfach bestimmten Problemen vorbeugen, welche vielleicht halt dann mal entstehen könnten, wenn man es halt "unsauber" macht.

    lg
    ScheduleLib 0.0.1.0
    Kleine Lib zum Anlaufen von Code zu bestimmten Zeiten
    Scheint so ja. Ich will einfach vermeiden, auf Probleme zu stoßen welche ab einer gewissen Projektgröße nur mehr schwer bis gar nicht mehr zu beheben sind. Ist in diesem Beispiel jetzt vielleicht übertrieben, aber ich will es halt gleich von Anfang an richtig machen.

    lg
    ScheduleLib 0.0.1.0
    Kleine Lib zum Anlaufen von Code zu bestimmten Zeiten
    Bezüglich unsauber oder sauber fand ich den Thread von @VincentTB ganz gut: Das Codebehind unter Benutzung des MVVMs
    MVVM ist eine gute Sache, aber man muss es auch nicht übertreiben und schon gar nicht heißt es, dass es absolut alles verbietet, was sich direkt im Codebehind aufhält. ;) Es ist okay, Events, Animationen etc. im Codebehind zu behandeln.

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    ja, nach meiner Vorstellung von Sauber ist MVVM aber vorzuziehen, wenn etwas bei gleichem Aufwand auch über MVVM lösbar ist.
    Einheitliche Vorgehensweise ist auch ein Faktor, der Übersichtlichkeit und Verständlichkeit verbessert (so mein logisches Schließen - steht aber bestimmt auch bei irgendwelchen Richtlinien-Machern nachzulesen).
    Danke für den Link @Trade!

    Ich denke es werde es für dieses Beispiel so belassen, dass im Loaded Event (welches ja mit der View zu tun hat) die Aktion des Viewmodels startet.
    Werde mir aber trotzdem dem Einwand von @thefiloe in dem Link ansehen, wo man Events am Commands binden kann. Hört sich interessant an.

    lg und Danke an alle!
    ScheduleLib 0.0.1.0
    Kleine Lib zum Anlaufen von Code zu bestimmten Zeiten