WPF - MVVM - Dialog - Warnung
-
Hallo zusammen,
Ich hätte mal eine Frage, wie ihr sowas lösen würdet in WPF und MVVM. Und zwar habe ich einen Dialog, welcher ein oder mehrere Felder beinhaltet, welche leer oder unübliche Werte enthalten dürfen. Wenn diese Werte auftreten, sollte allerdings beim Klicken auf Ok/Übernehmen/Speichern (etc.) eine Warnung dem Benutzer gezeigt werden. Der Benutzer kann dann entscheiden, ob die Eingabe wirklich so gewollt ist oder ob er sich nur vertippt, falsch ausgewählt oder was auch immer hat.
Ich bin gerade nah dran, dass ich von Window erbe und eine DependencyProperty hinzufüge, welche ich dann dazu verwende, wann der Dialog geschlossen wird. Damit könnte ich aus einem AcceptCommand im ViewModel entscheiden, ob der Dialog nun geschlossen werden soll oder nicht. Über den Mediator, bzw. DialogService, kann ich aus dem ViewModel meine Warnungen anzeigen.
Aber vielleicht habt ihr bessere Ideen
Grüssli
-
Und was haelst du von On-The Fly Validierung?
-
Firefighter schrieb:
Und was haelst du von On-The Fly Validierung?
Nicht viel aus folgender Argumentation:
Es gibt Validierungen, welche nicht nur zu einem Binding gehören. Wodurch Fehler angezeigt werden, welche gar keine sind, weil der User noch keine Eingabe gemacht hat. Daher kann man ihm keine MessageBox an den Kopf werfen, höchstens ein kleiner Hinweis am Rande. Das heisst aber wiederrum, dass Warnungen fast komplett übersehen werden. Fehler kann man sauber damit abfangen, da man z.B. den Accept-Knopf deaktivieren kann. Aber Warnungen sind ja keine Fehler. Man möchte den User nur kurz anstossen: "Hey! Meinst du das wirklich so oder ist dir da nicht ein Tippfehler unterlaufen oder hast du gar was vergessen?"On-The-Fly Validierung ist schön und gut für einfache Dinge. Für komplexeres halte ich es für unbrauchbar und muss beim Drücken auf den Accept-Knopf passieren. Was übrigens auch mein Kunde so hält und es so von mir verlangt hat, bevor ich was sagen konnte. Aber ich war dann einverstanden mit ihm
Hinweise sind zwar gut, werden aber viel zu schnell ignoriert oder vergessen.
Und wie gesagt, es geht hier ja eigentlich um Warnungen. Nicht um das Melden von Fehlern. Die Eingaben sind erlaubt, nur womöglich nicht erwünscht. Als wenn du den Betreff in einer E-Mail nicht angibst. Oder das Zahldatum einer Rechnung in die Zukunft setzt, obwohl sie normalerweise erst eingetragen werden, wenn sie bezahlt wurden. Ist zwar erlaubt, aber wahrscheinlich hast du den Betreff aus Versehen vergessen, bzw. das Datum falsch gesetzt.
Grüssli
-
Hast Du Dir die Implementierung von INotifyPropertyChanged und IDataErrorInfo schonmal genau angesehen? Damit lassen sich auch komplexere Validierungen implementieren. WPF markiert fehlerhafte Eingabefelder automatisch z.B. mit einem roten Rand, aber erst nachdem eine Eingabe gemacht wurde. Solche Hinweise kann man de Fakto nicht "vergessen" weil man sie ja direkt vor der Nase hat.
Genaugenommen ist die MessageBox eher problematisch weil sie das Kurzzeitgedächtnis des Benutzers fordert. Man muß sich ja merken welche Felder denn korrigiert werden müssen, da man die Box erst wegclicken muß um die Korrekturen zu machen. (Auch wenn es nru eine Warnung ist will man sie ja möglicherweise trotzdem korrigieren) Im Zusammenhang mit deiner Aussage das es ja auch komplexere Warnungen und/oder Fehlermeldungen sind wird der MessageBox Ansatz erst recht problematisch wenn er der Einzige Weg ist.
Was ganz anderes ist die Kombination mit einer on-the-fly validierung über IDataErrorInfo. Da kann man in der MessageBox lesen das man etwas falsch gemacht hat, muß es sich aber nicht merken weil man die betroffenen Felder auch in der GUI markiert sind.
-
@loks,
Schöne Theorie, in der Praxis sieht das aber anders aus. Da wird gerne mal viel zu schnell auf den Ok-Button gedrückt. Wie ich schon sagte, bei einem Fehler ist das kein Problem, da man den Ok-Button deaktivieren kann. Bei einer Warnung dagegen kannst du das nicht! Und darum geht es hier! Siehe Titel! Siehe Eingangsbeitrag!Ja, ich verwende
IDataErrorInfo
- für Fehler! Alle meine ViewModel implementieren dank einer gemeinsamen Basisklasse automatischIDataErrorInfo
, welches dann auch automatisch mit den Properties verbunden werden, welche automatischPropertyChanged
Events auslösen und sich validieren. Hab mir da alles schön zusammengebaut mit Debug-Prüfung ob die Properties auch existieren usw. usf.Und der Kunde ist der Meinung, dass seine Mitarbeiter ein 2 Sekunden Kurzzeitgedächnis besitzen. Man kann zudem auch noch mit Fokus arbeiten, so dass der Fokus automatisch auf das richtige Element im GUI gesetzt wird. Und falls er wirklich alles immer wieder gleich vergisst, könnte er ja erneut auf den Ok-Button klicken. Ich darf doch bitten...
Zudem könnte man die Warnung auch am oberen Rand noch zusätzlich erscheinen lassen, falls man wirklich mit Leuten zusammenarbeitet, welche nicht mal einen Fuss vor den anderen setzen könnenDer Punkt bleibt aber am Ende. Beim Drücken auf dem Button muss eine Warnung erfolgen. Die Chance ist sonst zu gross, dass so eine Warnung übersehen wird. Gewisse Eingaben haben gar keine Fehlerzustände und nur eine allfällige Warnung. Oder der Mitarbeitet gibt die Daten schnell ein und bedient den Dialog so schnell, das ihm die Warnung gar nicht auffällt. Es gibt Arbeitschritte, welche von Mitarbeiter blind verrichtet wird. Heisst sie schauen gar nicht auf den Bildschirm während sie die Eingaben machen, da sie irgendwelche Daten abtippen oder dergleichen. Da ist es sehr gut, wenn dann bei Enter ein "Ding" ertönt und eine Warnung auf dem Bildschirm erscheint.
Ich weiss, es entspricht nicht der aktuellen Mode, aber man entwickelt nicht Programme nach der aktuellen Mode, sondern nach dem was der Kunde benötigt.
Grüssli
-
Hmm mir scheint so als wenn du deine Loesung doch eh schon kennst, weil bisher hast du alle Vorschlaege rigoros abgeschmetert
Ich wuerde sagen, deine Idee fuer die Umsetzung ist in deinem Fall die einzig gute.
-
Firefighter schrieb:
Hmm mir scheint so als wenn du deine Loesung doch eh schon kennst, weil bisher hast du alle Vorschlaege rigoros abgeschmetert
Naja, die Vorschläge bezogen sich aber nicht wirklich auf meine Problemstellung. Sie bezogen sich eher auf Fehlermeldungen. Es geht aber eben nicht um Falscheingaben. Und ich will definitiv eine MessageBox anzeigen.
Die Frage ist halt eben eher, wie man dies am besten hinbekommt im Kontext von MVVM und WPF. Und meine Lösung stört mich irgendwie, aber ich kann es nicht so recht greifen. Der Thread soll also auch dazu dienen, dass ich mir klar darüber werde, was mich daran stört
Grüssli
-
Im Gegensatz zu uns hast Du den Vorteil das Du die Anforderungen und kennst. Es ist schwer eine Lösung für ein Problem vorzuschlagen das man nicht kennt. Und wenn Du meinen Beitrag mal bis zu Ende liest wirst Du sehen das ich eine Kombination aus on-the-fly und Messagebox vorgeschlagen habe.
Ich benutze die gleiche Kombination in einem meiner Tools. Felder die von den Empfehlungen abweichen werden mittels IDataErrorInfo markiert und im Tooltip steht dann der Hinweis. Klickt der Kunde auf "OK" kommt dann eine Zusammenfassende Messagebox. Bei harten Fehlern muß er diese natürlich erst auflösen.
Ansonsten... Kunden wissen nur was sie wollen, selten was die brauchen. Dieses "Der Kunde will es aber so" bedeutet im Zweifelsfalle nur das Du selbigen schlecht beraten hast.
-
Du brauchst doch nur eine Möglichkeit das Schließen des Fensters aus dem ViewModel heraus zu beeinflussen.
Das habe ich zb in meinem WindowBehavior.<Window * xmlns:Interactivity="http://schemas.my-libraries.de/wpf/interactivity" *> <Button Content="OK" Interactivity:WindowBehavior.DialogResultCommand="{Binding ClosingCommand}" /> </Window>
namespace * { public partial class *ViewModel : ObservableObject { public DemoWindow() { ClosingCommand = new DelegateCommand<WindowClosingArgs>(WindowClosing); } public ICommand ClosingCommand { get; set; } private void WindowClosing(WindowClosingArgs e) { // Validate here, // e.Cancel will cancel the closing process // The DialogResult will be true as default, but it can be modified with e.DialogResult var messageBoxService = ServiceLocator.Resolve<IMessageBoxService>(); if (messageBoxService.Show(this, "Close?", "Demo", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.No) e.Cancel = true; } }
-
@David W,
Danke! Der Parameter beiICommand
kann ich dazu ja benutzen. Gute Idee! An ein Behavior hatte ich zwischenzeitlich auch schon gedacht, aber nicht über ein zusätlichesICommand
.Ich überlege mir aber gerade trotzdem noch, ob ich nicht ein DialogWindow erstelle, welches dann aber dieses Command zur Verfügung stellt, an welches sich dann das ViewModel bindet.
@loks,
Ich habe deinen Beitrag vollständig gelesen. Ich habe aber nicht nach dem gesucht, was du mir vorgeschlagen hast. Ich habe bereits on-the-fly Validierung drin! Ich habe nach einer Möglichkeit gefragt, wie man eine Warnung aus der ViewModel auslösen kann und dabei auch steuern kann, ob sich der Dialog schliesst oder nicht.
Ich habe nie danach gefragt, wie man on-the-fly Validierung macht! David W ist hier der erste, welcher auf meine eigentliche Frage eingeht.Und ja, ich kenne die 5 Warums beim Requirement Engineering. Die Gründe wieso der Kunde dies möchte sind mir bekannt und machen Sinn. Es ist das was er will.
Grüssli