Searchbox Windows 8.1

Die Suche in Windows 8.1 ist eine glatte Kehrtwendung von Microsoft. Statt im Charm Bar, wird wieder direkt in der Anwendung gesucht. Nur wenige neue Anwendungen beinhalten aktuell (Oktober 2013) das dafür vorgesehene SearchBox Control. Die auf Windows 8.1 vorinstallierten Bing Weather oder Bing Stocks App lassen erahnen wohin die Reise geht.

image

Zusätzlich bietet das XAML Steuerelement eine Vorschlagsliste, die bei Bedarf auch Bilder anzeigen kann. Hier ein Screenshot aus der Kontakte App.

image

Das Standardverhalten ist bisherige Suchbegriffe als Vorschlagsliste anzuzeigen. Alternativ ( oder auch zusätzlich, lassen sich die Vorschläge auch aus einem Service oder lokalen Daten generieren. Dazu wurde im XAML die Search Historie deaktiviert und das Event Suggestion Requested anprogrammiert.

Über das Property FocusOnKeyboard, wird die Suche verwendet, sobald der Benutzer am Keyboard eine Taste drückt. Auch wenn gerade ein anderes UI Element den Focus hat. Ganz wie der Windows 8.1 Startscreen.

   1:  <SearchBox  FocusOnKeyboardInput="True"
   2:       QuerySubmitted="SearchBox_QuerySubmitted"
   3:       SuggestionsRequested="SearchBox_SuggestionsRequested"
   4:       SearchHistoryEnabled="False">
   5:  </SearchBox>

In diesem konkreten VB.NET Beispiel werden Ozon Messdaten in einer Listview angezeigt. Die Daten sind als JSON direkt im Projekt eingebettet.

Wenn der Benutzer sucht, wird per LINQ Query die Filterung durchgeführt.

   1:   Dim l As List(Of Messstation)
   2:      Private Async Sub MainPage_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
   3:          Dim sf = Await StorageFile.GetFileFromApplicationUriAsync(New Uri("ms-appx:///ozon.json"))
   4:          Dim js = Await sf.OpenStreamForReadAsync
   5:          Dim ser As New DataContractJsonSerializer(GetType(List(Of Messstation)))
   6:          l = CType(ser.ReadObject(js), List(Of Messstation))
   7:   End Sub
   8:   
   9:  Private Async Function SearchBox_QuerySubmitted(sender As SearchBox, args As 
SearchBoxQuerySubmittedEventArgs) As Task
  10:          Dim query = From item In l
  11:                      Where item.name.Contains(args.QueryText)
  12:                      Select item
  13:          liste0.ItemsSource = query
  14:   End Function

Etwas spannender ist die Vorschlagsliste. Über die Eventargs erhält man Zugriff auf die Systemvorschlagsliste und kann dort Einträge einzeln per AppendQuerySuggestion anhängen. Oder man nimmt gleich eine ganze Liste von Strings, wie im folgenden VB.NET Code Sample.

   2:      Private Sub SearchBox_SuggestionsRequested(sender As SearchBox, 
args As SearchBoxSuggestionsRequestedEventArgs)
   4:          Dim queryText = args.QueryText
   5:          If Not String.IsNullOrEmpty(queryText) Then
   6:              Dim query = From item In l
   7:                              Where item.name.Contains(args.QueryText)
   8:                              Select item.name
   9:                              Take 10
  10:              Dim sugColl As SearchSuggestionCollection =
  11:                  args.Request.SearchSuggestionCollection
  12:              sugColl.AppendQuerySuggestions(query)
  13:          End If
  14:      End Sub
  16:    

In meinen Versuchen habe ich den Filezugriff in die Methode SuggestionsRequested gelegt, in der Art :

   1:     Private Async Sub SearchBox_SuggestionsRequested(sender As SearchBox, 
args As SearchBoxSuggestionsRequestedEventArgs)
   2:          Dim sf1 = Await StorageFile.GetFileFromApplicationUriAsync(New Uri("ms-appx:///ozon.json"))
   3:   

Geerntet habe ich eine Exception in der Zeile 12 (AppendQuery).

A first chance exception of type 'System.InvalidOperationException' occurred in App2.exe. WinRT information: Eine Methode wurde zu einem unerwarteten Zeitpunkt aufgerufen.

Oder auf Englisch:

System.InvalidOperationException: A method was called at an unexpected time

Fürs erste war ich ratlos. Tim Heuer von Microsoft hat mich auf die passende Lösung gestoßen. Genau wie im OnSuspending Event, muss man sich aus den Eventargs die Referenz auf das Deferal holen, um nicht in Timing Probleme zu laufen.

   1:  Dim deferral = args.Request.GetDeferral()
   2:  Dim foo = Await Windows.Storage.StorageFile.GetFileFromApplicationUriAsync(
New Uri("ms-appx:///assets/logo.png"))
   3:  args.Request.SearchSuggestionCollection.AppendQuerySuggestion("test")
   4:  deferral.Complete()
Kommentare sind geschlossen