Windows 10.2 Apps Eingabe validieren

Ein übliches LOB Programm besteht hauptsächlich aus Listen und Eingabe Dialogen. Der Benutzer als natürlicher Feind versucht ständig durch Fehleingaben den Entwickler bloß zu stellen. Das wollen wir Developer natürlich verhindern. Erste Versuche einfach den OSI Layer 8 zu eliminieren, wurden von der Management Schicht schnell abgewürgt. Wir kriegen den Benutzer einfach nicht weg.

Im zweiten Schritt verhindern wir einfach fehlerhafte und ungültige Eingaben in Textboxen, oder eliminieren die Auswahlmöglichkeiten durch Optionen oder Drop Downlisten. Das bedeutet, ein Großteil des Programmcode kümmert sich drum, das etwas nicht passiert. Z.B. in einer Leipziger Postleitzahl “ossi” steht.

In klassischen Architekturen, ist man dann auf den Trichter gekommen, die Regeln einfach aus der Datenbank zu nehmen und diese dann bis ins User Interface durchzureichen. Die Data Annotations wurden geboren. In der Datenklasse werden durch Attribute ein oder mehrere Regeln auf Eigenschaften definiert. Sogar Beschriftung und Fehlermeldung sind so definierbar.

   1:  <Display(Name:="Name")> _
   2:  <Required()> _
   3:   Public Property ProductName() As String

Wer Entity Framework nutzt um seine Models aus der Datenbank zu bauen, bekommt das auch automatisch generiert. Je nach verwendeter UI Technologie wird dies mal besser (Silverlight, ASP.NET Webforms, mal so lala (WPF) und mal quasi gar nicht verwertet. Damit wären wir bei UWP und Windows 10. Diese APP’s können weder Annotation zur Validierung nutzen, noch bieten die Controls eingebaute Error Templates um Fehlermeldungen überhaupt anzeigen zu können.

Aus Microsoft Sicht könnte man nun vorsichtig wie folgt formulieren

“da METRO, Store Anwendungen von niemanden genutzt werden, haben wir einfach die Datenbank Unterstützung weggelassen und gehofft das es nicht auffällt. ADO.NET und Entity Framework sind doch ohnehin obsolet. Ist alles REST heute. Für die paar Vollfreaks die noch auf SQL stehen, verweisen wir auf unbekanntes Fremdprodukt SQLite. Also was willste mit Annotations da überhaupt noch?!!!!”

Und in der Tat ist klassische Validierung mit Fehlermeldungen im UI in weiten Teilen nicht mehr zeitgemäß. Das User Interface muss Falscheingaben im Ansatz vernichten (oje schon wieder ein User weniger). Manchmal geht’s aber nicht und man muss eine freundliche Fehlermeldung anzeigen und den Benutzer so anleiten korrekte Aktivitäten auszuführen

Die Frage ist also, wie kann man mit Data Annotations und UWP doch arbeiten. Vermutlich um Code besser zwischen Projekten sharen zu können, gibt es die nötigen DLLs per Nuget auch für Universal Apps. Einfach Nuget anwerfen und System.Componentmodel samt Annotations ins Visual Studio Projekt installieren.

image

Folgender VB.NET Code aus einer Model Klasse, wird dann auch vom Compiler akzeptiert

   1:   <Required()>
   2:   <StringLength(5)>
   3:      Public Property name As String

 

Nur nutzt das nichts um niemand. Man muss Klassenattribute auch verarbeiten können. Dafür gibt es das PRISM 6 Framework aus der Pattern und Practice Gruppe bei Microsoft. Es wäre jetzt auch zu leicht einen Joke dazu unterzubringen. Installiert wird die Assembly wieder per Nuget. Für Pragmatiker per UI und die anderen nutzen die Packet Manager Konsole in Visual Studio.

Das ViewModell erbt dann von BindableBase aus dem Namensraum Prism.MVVM.

   1:  Imports Prism.Mvvm
   2:   
   3:  Public Class ClassVM
   4:      Inherits BindableBase

 

Damit erhält jede komplexe Eigenschaft im Viewmodel ein Error Objekt und eine Test Methode Validatepropertys. Diese prüft die einzelnen Propertys des Objektes gegen die Annotationen und füllt ggf die Fehlerliste.

Hört sich jetzt komplizierter an als es ist. Stellt sich noch die Frage, wann man die Überprüfung realisiert. Da UWP ohnehin erst beim verlassen (lostfocus) eines Eingabe Steuerelements, den Update des Databindings anstößt, kann man auch einen simplen Save Button verwenden und einfach alles auf einen Rutsch checken.

Die komplexe Eigenschaft test besitzt ein Property name. (der Autor entschuldigt sich für die bes…. Namen). Durch Prism Hokuspokus wird das Objekt test um z.B die Error Liste erweitert. Konkret vom Typ BindableValidator per Index. Für jedes Property, hier name, von test (sorry,sorry) kann ein oder mehr Fehler vorliegen. Das VB.NET Beispiel zeigt drei Varianten um auf die eigenlichen Fehlermeldungen zugreifen zu können.

   1:   Public Sub button1()
   2:          If Not test.ValidateProperties Then
   3:              Dim y = test.Errors.GetAllErrors()("name")(0)
   4:              Dim x = test.Errors("name")(0)
   5:              Dim z = CType(test.Errors.Errors, Dictionary(Of String, ReadOnlyCollection(Of String)))
   6:          End If

Sehr böser Benutzer lässt Feld leer, das er eigentlich ausfüllen sollte. Im Debugger von Visual Studio kann man dann den generischen Error Text “the name field is required” schon auslesen.

image

Auch wenn es oft wünschenswert wäre, Visual Studio einfach mit Source Code auszuliefern, wird der ordinäre Benutzer seine Eingabe Fehler so nicht mitgeteilt bekommen. Wir müssen das UI und damit XAML damit beauftragen. Für die Anzeige der/des Fehlers werden eigene UI Elemente wie Textblock benötigt. Hier ganz altbacken rot gefärbt.

Es ist nun in WIndows 10 Anniversary möglich Indexer zu verwenden, mit leicht geänderter Syntax zu Binding

<TextBlock Text="{x:Bind mydx.test.Errors['name'][0],Mode=OneWay}"/>

Das klappt aber nicht. Der Kompiler wehrt sich mit einer Fehlermeldung unexpected Array Indexer. Ich vermute, das es ein Problem mit dem Casting gibt. Auch explizites Casting scheitert da für den Dictionary Typ in C# <> verwendet werden und das in XAML nicht zulässig ist. Und Dokumentation gibt es nicht, weil das liest ohnehin keiner der 10 UWP Developer.

Bleibt nur der konservative Weg über die Binding Markup Extension, die erst zur Laufzeit ausgewertet wird.

   1:  <TextBox Text="{Binding  test.Errors[name][0]}"/>
   2:  <ListView ItemsSource="{Binding test.Errors[name]}">
   3:                  <TextBlock Text="{Binding}" Foreground="Red" />
   4:  </ListView>
Man kann compiled Binding und Datacontext auch gemischt verwenden, wie hier beschrieben.

 

Natürlich kann man eine UWP Schulung auch bei ppedv buchen.

Kommentare sind geschlossen