Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Win 8.1 SearchBox - binding suggestions

We are writing a Windows 8.1 Store App that uses the new SearchBox XAML control. It looks like the only way to get suggestions into the dropdown list as the user types is to use the SearchBoxSuggestionsRequestedEventArgs and get the SearchSuggestionCollection from the event then append the suggestions to that.

We're using Prism for WinRT and want to separate the SearchBox and it's events from the ViewModel that is getting the list of suggestion strings.

I can't find anyway of binding a list of strings to the SearchSuggestionCollection or any way of adding them programatically that doesn't involve using the event args, which is making out unit testing very complex.

Is there a way of binding/adding the suggestions that doesn't involve the event args?

like image 727
Colin Desmond Avatar asked Nov 20 '13 09:11

Colin Desmond


1 Answers

Okay, so I got obsessed with this question, and here is a solution for when using the SearchBox. I've uploaded a full sample on MSDN and GitHub

In short, use the Behavior SDK and and the InvokeCommand, and then use a converter to grab whatever data you need by using the new attributes InputConvert and InputConverterParameter.

XAML:

    <SearchBox SearchHistoryEnabled="False" x:Name="SearchBox" Width="500" Height="50">
        <SearchBox.Resources>
            <local:SearchArgsConverter x:Name="ArgsConverter"/>
        </SearchBox.Resources>
        <interactivity:Interaction.Behaviors>
            <core:EventTriggerBehavior EventName="SuggestionsRequested">
                <core:InvokeCommandAction
                    Command="{Binding SuggestionRequest}"
                    InputConverter="{StaticResource ArgsConverter}"
                    InputConverterLanguage="en-US"
                    InputConverterParameter="{Binding ElementName=SearchBox, Path=SearchHistoryEnabled}"/>
            </core:EventTriggerBehavior>
        </interactivity:Interaction.Behaviors>
    </SearchBox>

Converter:

 public sealed class SearchArgsConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        var args = (SearchBoxSuggestionsRequestedEventArgs)value;
        var displayHistory = (bool)parameter;

        if (args == null) return value;
        ISuggestionQuery item = new SuggestionQuery(args.Request, args.QueryText)
        {
            DisplayHistory = displayHistory
        };
        return item;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        return value;
    }
}

Mainpade codebehind - of course you want this in a VM :)

 public sealed partial class MainPage
{
    public DelegateCommand<string> Search { get; set; }
    public DelegateCommand<ISuggestionQuery> SuggestionRequest { get; set; }

    public MainPage()
    {
        InitializeComponent();
        Search = new DelegateCommand<string>(SearchedFor, o => true);
        SuggestionRequest = new DelegateCommand<ISuggestionQuery>(SuggestionRequestFor, o => true);

        DataContext = this;
    }

    private void SuggestionRequestFor(ISuggestionQuery query)
    {
        IEnumerable<string> filteredQuery = _data
            .Where(suggestion => suggestion.StartsWith(query.QueryText,
                StringComparison.CurrentCultureIgnoreCase));
        query.Request.SearchSuggestionCollection.AppendQuerySuggestions(filteredQuery);
    }

    private readonly string[] _data = { "Banana", "Apple", "Meat", "Ham" };

    private void SearchedFor(string queryText)
    {
    }
}

I wrote up a full walk through on my blog, but the above is all you really need :)

like image 63
Iris Classon Avatar answered Sep 29 '22 20:09

Iris Classon