Services , IDialogWindowService

  • WPF MVVM
  • .NET 5–6

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von Nofear23m.

    Services , IDialogWindowService

    Hallo zusammen,
    ich versuche mich gerade an den Services im MVVM Pattern. (Code ist von @Nofear23m , ich habe ihn nur übsersetzt nach C#)
    Den MessageBoxService habe ich schon hinbekommen und der funktioniert auch.
    Allerdings habe ich ein Problem beim DialogWindowService.
    Ich habe das Interface IDialogWindowService:
    Spoiler anzeigen

    C#-Quellcode

    1. public interface IDialogWindowService
    2. {
    3. bool ShowModalDialog(string windowName, object dataContext, object owner, bool topMost = false, bool showInTaskbar = true);
    4. void CloseDialog();
    5. void CloseDialog(object vm);
    6. }


    Die Klasse die das Interface Implementiert:
    Spoiler anzeigen

    C#-Quellcode

    1. public class DialogWindowService : IDialogWindowService
    2. {
    3. private DialogWindow _currentDialogWindow;
    4. public bool ShowModalDialog(string windowName, object dataContext, object owner, bool topMost = false, bool showInTaskbar = true)
    5. {
    6. DialogWindow dialogwindow = new DialogWindow(windowName, dataContext, System.Windows.SizeToContent.WidthAndHeight, System.Windows.WindowStartupLocation.CenterOwner);
    7. _currentDialogWindow = dialogwindow;
    8. dialogwindow.Topmost = topMost;
    9. dialogwindow.ShowInTaskbar = showInTaskbar;
    10. dialogwindow.Owner = dialogwindow.FindOwnerWindow(owner);
    11. dialogwindow.AsDialogWindowModalDialog = true;
    12. return (bool)Application.Current.Dispatcher.Invoke(() => dialogwindow.ShowDialog);
    13. //return System.Convert.ToBoolean(Application.Current.Dispatcher.Invoke(() => dialogwindow.ShowDialog));
    14. }
    15. public void CloseDialog()
    16. {
    17. if (_currentDialogWindow != null)
    18. {
    19. _currentDialogWindow.Close();
    20. }
    21. }
    22. public void CloseDialog(object vm)
    23. {
    24. Window owner = Application.Current.Windows.Cast<Window>().SingleOrDefault(x => x.DataContext != null && x.DataContext.GetType() == vm.GetType());
    25. if (owner == null)
    26. {
    27. foreach (Window window in (from Window win in Application.Current.Windows
    28. select win).ToList())
    29. {
    30. if (window.DataContext.GetType() == vm.GetType())
    31. window.Close();
    32. }
    33. }
    34. else
    35. owner.Close();
    36. }
    37. }


    bei folgendem Aufruf bekomme ich dann eine Exception die ich nicht verstehe und ich keine Ahnung habe wo ich überhaupt suchen soll.

    C#-Quellcode

    1. ServiceContainer.GetService<IDialogWindowService>().ShowModalDialog("Windowname", new ViewModel1(),this);


    Exception:
    System.InvalidCastException: "Unable to cast object of type 'System.Func`1[System.Nullable`1[System.Boolean]]' to type 'System.Boolean'."

    Markiert wird folgende Zeile:

    C#-Quellcode

    1. return (bool)Application.Current.Dispatcher.Invoke(() => dialogwindow.ShowDialog);


    Ich habe auch schon

    C#-Quellcode

    1. return System.Convert.ToBoolean(Application.Current.Dispatcher.Invoke(() => dialogwindow.ShowDialog));
    probiert.
    Aber auch da kommt der gleiche Fehler.
    Kann mir da jemand sagen was ich falsch übersetzt habe und was die Fehlermeldung genau bedeutet?

    Edit: Noch ein TestProjekt angehangen!
    Dateien
    Rechtschreibfehler betonen den künstlerischen Charakter des Autors.
    Hallo

    Naja, ich nehme an du proggst unter .Net 6. Hier musst du nun eben wie in der Meldung ersichtlich zwischen Nullable Bool und Bool unterscheiden.

    Der WindowsDialog wird bool? zurückgeben und du willst es aber eben in bool casten was nicht geht.

    Grüße

    Edit: Das müsste dir die IDE aber anzeigen mit einer Warnung und einer Wellenlinie oder?
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Wie Nofear23m schon sagt: Es ist ein Nullable Boolean,

    Nullable Typen sind wie primitive Typen, mit dem Unterschied, dass sie zusätzlich den Zustand ​null annehmen können.

    Die einfachste Option ist, dass du in der Return-Anweisung castest:

    C#-Quellcode

    1. ​return (bool?)Application.Current.Dispatcher.Invoke(() => dialogwindow.ShowDialog);


    wobei du das Casting dann weglassen kannst, da es ohnehin bool? zurückgibt. Deine Funktion im Service muss dann entsprechend so angepasst werden, dass sie statt eines Boolean einen Nullable Boolean zurückgibt. Dies erreichst du durch das Anhängen eines ? am Typen.

    Das Casten geht nur deshalb nicht, da ein Nullable Boolean ja auch null annehmen kann, was ein bool nicht verwerten kann. Wenn du bei deiner Funktion bleiben möchtest, dann kannst du das ganze auch mittels eines Ausrufezeichen versehen. Damit sagst du dem Compiler, dass in deinem Nullable Boolean zu diesem Zeitpunkt definitiv kein null-Wert enthalten sein kann. Dann meckert er auch nicht mehr. Solltest du dann dennoch mal null drin haben, wird dein Programm abstürzen und die Fehlersuche könnte sich erschweren - weshalb ich davonabrate.
    Hallo zusammen,

    Nofear23m schrieb:

    Der WindowsDialog wird bool? zurückgeben und du willst es aber eben in bool casten was nicht geht.

    Ok, das habe ich verstanden. Es sind zwei unterschiedliche Typen.

    Nofear23m schrieb:

    Das müsste dir die IDE aber anzeigen mit einer Warnung und einer Wellenlinie oder?

    War leider nicht so, deshalb habe ich mich auf Fehlersuche begeben warum das nicht so ist, denn es sollte ja so sein wenn ich dich richtig verstanden habe.
    Fehler lag an Visual Studio. Wenn ich neue Projekte anlege ist bei mir der Wert

    XML-Quellcode

    1. <Nullable>disable</Nullable>
    in der Projektdatei hinterlegt. Das sollte ja eigentlich automatisch

    XML-Quellcode

    1. true
    sein. Ich habe das Händisch geändert und bekomme nun einen Haufen Warnungen. Die meisten davon überfordern mich erstmal :/

    PadreSperanza schrieb:

    return (bool?)Application.Current.Dispatcher.Invoke(() => dialogwindow.ShowDialog);

    Bringt nicht den gewünschten Erfolg. Wirft weiter Fehler und Warnungen.

    XML-Quellcode

    1. ​Schweregrad Code Beschreibung Projekt Datei Zeile Unterdrückungszustand
    2. Fehler CS0266 Der Typ "bool?" kann nicht implizit in "bool" konvertiert werden. Es ist bereits eine explizite Konvertierung vorhanden (möglicherweise fehlt eine Umwandlung).
    3. Schweregrad Code Beschreibung Projekt Datei Zeile Unterdrückungszustand
    4. Warnung CS8619 Die NULL-Zulässigkeit von Verweistypen im Wert vom Typ "bool?" entspricht nicht dem Zieltyp "bool".


    Wenn ich das ganze jetzt richtig verstanden habe soll die Funktion laut Signatur ein bool zurückgeben , in der Returnanweisung kommt aber ein bool? raus. Sprich, das passt nicht weil unterschiedliche Typen.
    Casten funktioniert nicht. Da dachte ich ändere ich den Rückgabetypen im Interface und in der Funktion auf bool? und es würde passen. Leider klappt auch das nicht. Irgendwas verstehe ich daran nicht. Das Thema ist für mich ziemlich neu.
    Rechtschreibfehler betonen den künstlerischen Charakter des Autors.

    Akanel schrieb:

    Das Thema ist für mich ziemlich neu.

    Ne, ist es nicht. Wirkt nur so auf dich. Es wäre ja das selbe wenn die ShowDialog() dir double zurückgeben würde und deine Methode erwartet ein int.

    Also, entweder du änderst den Rückgabetypen deiner Methode ab (im Interface natürlich auch):

    VB.NET-Quellcode

    1. ​public bool? ShowModalDialog(string windowName, o......

    und gibt den Wert dann wie folgt zurück:

    VB.NET-Quellcode

    1. return ​Application.Current.Dispatcher.Invoke(() => dialogwindow.ShowDialog)


    Oder, um nichts an deinem Interface ändern zu müssen (weil du es evtl. bereits an einigen stellen der Applikation nutzt):

    VB.NET-Quellcode

    1. bool? dialogResult = ​Application.Current.Dispatcher.Invoke(() => dialogwindow.ShowDialog);
    2. return dialogResult == null ? false : dialogResult.Value


    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Hallo Sascha,

    danke für deine Bestätigung das ich mit dem ändern des Rückgabetypen richtig lag. Somit habe ich das doch richtig verstanden.
    Warum es bei mir dennoch nicht funktioniert hatte, lag daran das

    C#-Quellcode

    1. return Application.Current.Dispatcher.Invoke(() => dialogwindow.ShowDialog)

    eigentlich

    C#-Quellcode

    1. return Application.Current.Dispatcher.Invoke(() => dialogwindow.ShowDialog())

    lauten muss.

    Nun funktioniert es wie gewünscht und ich kann mich den anderen Warnungen widmen.

    Vielen Dank.
    Rechtschreibfehler betonen den künstlerischen Charakter des Autors.

    Akanel schrieb:

    lauten muss.

    Sorry, hatte ich auch jetzt nicht darauf geachtet, ging davon aus das der Rest des Codes in Ordnung wäre ;)

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##