Eingabefehler abfangen in Windows 8 Store APP’s

by Hannes Preishuber22. September 2012 12:32

Anders als in WPF oder Silverlight, hat das XAML UI Framework von WInRT keine Templates oder Mechanismen um Fehler an den Benutzer zu melden oder ihn zu leiten. Also ist in WinRT Handarbeit angesagt für das Errorhandling.

Optisch erscheint es sinnvoll, über eine Textbox einen rot eingefärbten Textblock zu platzieren, die über das Visbility Attribut gesteuert wird. Um es einheitlich im Layout handhaben zu können, bietet sich eine Gruppierung mit Stackpanel an.

image

Nun stellt sich díe Frage, wie man die Logik unterbringt. VB.NET Entwickler werden aus jahrelanger Erfahrung gerne zum lostfocus Event greifen.

Das Problem ist, das man auch das Event GotFocus nutzen muss, um die Fehlermeldung wieder auszublenden, wenn der Benutzer den Cursor in die Textbox zurück setzt. Folgender VB.NET Code prüft auf ein X und meldet dann einen Fehler.

 Private Sub TextBox_LostFocus_1(sender As Object, e As RoutedEventArgs)
If sender.text.contains("x") Then
errorTextbox1.Visibility = Windows.UI.Xaml.Visibility.VisibleEnd IfEnd SubPrivate Sub TextBox_GotFocus_1(sender As Object, e As RoutedEventArgs)
errorTextbox1.Visibility = Windows.UI.Xaml.Visibility.CollapsedEnd Sub

Der Code sieht etwas seltsam aus (wo ist der Typcast) funktioniert aber so unter Windows 8.

Wenn man allerdings Databinding verwendet, ergeben sich neue Problemstellungen. Ich setze hier eine Klasse class1 mit einem Property prop vom Typ String.

 <TextBlock Foreground="Red" Text="Bitte die Eingabe überprüfen" Visibility="Collapsed"
x:Name="errorTextbox1"></TextBlock><TextBox HorizontalAlignment="Left" TextWrapping="Wrap" Text="{Binding prop,Mode=TwoWay}"
GotFocus="TextBox_GotFocus_1" LostFocus="TextBox_LostFocus_1" VerticalAlignment="Top"/>

Die Zuweisung der Datenquelle erfolgt über den DataContext

Private Sub MainPage_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.LoadedDim c As New Class1
c.prop = "test"Me.DataContext = cEnd Sub

Um auf den Inhalt des Datacontext zugreifen zu können, wird man unter Umständen, die vorige Codezeile einfach umdrehen. Das klappt aber in Lostfocus nicht, bzw liefert den letzten Inhalt der Textbox und nicht den aktuellen.

Also folgender Code erzeugt ein falsches seltsames verzögertes Verhalten.

 Private Sub TextBox_LostFocus_1(sender As Object, e As RoutedEventArgs)
If Me.DataContext.prop.Contains("x") Then
errorTextbox1.Visibility = Windows.UI.Xaml.Visibility.VisibleEnd IfEnd Sub

In WPF lässt sich das mit der BindingExpression und UpdateSource umgehen. Ich habe aber keine WinRT .NET Entsprechung gefunden.

Ist auch nicht essentiell, da es wahrscheinlich sinniger ist, die mit zwei Events nötige komplexe Logik in die Hände des Class1 Objektes zu geben. Diese bekommt dazu eine Eigenschaft isValid, die dann folgend an die ErrorTextbox gebunden wird. Da allerdings die Textbox zwar in das Objekt schreiben kann, aber nichts davon mitbekommt, wenn sich der Inhalt des isValid Propertys nachträglich ändert, muss diese davon unterrichtet werden. Das wird über ein Nachrichtensystem implementiert, das das Interface InotifyPropertyChanged mitliefert. Wenn sich isValid verändert wird dann per Code das Event erzwungen (raisevent).

Ergänzend: in .NET 4.5 gibt es nun einen Methode CallMemberName, die etwas weniger Code benötigt.

Public Class Class1Implements INotifyPropertyChangedPrivate _prop1 As StringPublic Property prop() As StringGet
Return _prop1End GetSet(ByVal value As String)
If value.Contains("x") Then
isValid = Visibility.VisibleElse
_prop1 = value
isValid = Visibility.CollapsedEnd If
End SetEnd PropertyPrivate _isValid As Windows.UI.Xaml.VisibilityPublic Property isValid() As Windows.UI.Xaml.VisibilityGet
Return _isValidEnd GetSet(ByVal value As Windows.UI.Xaml.Visibility)
_isValid = valueRaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("isValid"))
End SetEnd PropertyPublic Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) 
Implements INotifyPropertyChanged.PropertyChangedEnd Class

Über die Implementierung von Überprüfungslogik kann man trefflich diskutieren. Wahrscheinlich wird man in der Praxis noch ein Fehlerobjekt mit Details mitführen. In Silverlight musste man z.B. Exceptions auslösen. Wie man sehen kann, hat man nun nur mehr Code an einer Stelle (im Datenobjekt) und keinen Code mehr in der Seite (im View). Richtig, das deckt sich mit dem Design Pattern MVVM.

Die Bindung in XAML ist nun ein leichtes und beinhaltet keine Überraschungen.

<StackPanel>
<TextBlock Foreground="Red" Text="Bitte die Eingabe überprüfen" Visibility="{Binding isValid}" 
/> <TextBox HorizontalAlignment="Left" TextWrapping="Wrap" Text="{Binding prop,Mode=TwoWay}"

Als Steigerungsstufe (ab hier optionales weiterlesen) wird auch noch der Code aus dem Load Event des Views eliminiert. Auch das geht per Binding im XAML.

<Page.Resources><local:Class1 x:Key="class1"/></Page.Resources><StackPanel DataContext="{StaticResource class1}"
Wenn ihnen der Artikel gefallen hat oder er für sie hilfreich war, bitten "kicken" sie ihn.
kick it on dotnet-kicks.de

Tags:

.Net | VB | WinRT | Windows | XAML

Pingbacks and trackbacks (1)+

Kommentar schreiben

  Country flag

biuquote
  • Kommentar
  • Live Vorschau
Loading

About the author

Something about the author

Month List

Page List