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.
Zusätzlich bietet das XAML Steuerelement eine Vorschlagsliste, die bei Bedarf auch Bilder anzeigen kann. Hier ein Screenshot aus der Kontakte App.
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()