Windows 8.1 introduced the new SearchBox control that provides built-in functionality for searching content in the apps.

This control raises QuerySubmitted event when we submit a search passing QueryText property in the event args (of type SearchBoxQuerySubmittedEventArgs).

When we use MVVM pattern in Windows Store apps, we define commands in the viewmodels, for example with Prism framework we define a DelegateCommand.

To invoke the command when then search is submitted, we can use behaviors:



<SearchBox>
    <interactivity:Interaction.Behaviors>
        <behaviors:OpacityToVisibilityBehavior />
        <core:EventTriggerBehavior EventName="QuerySubmitted">
            <core:InvokeCommandAction Command="{Binding SearchCommand}" />
        </core:EventTriggerBehavior>
    </interactivity:Interaction.Behaviors>
</SearchBox>


InvokeCommandAction automatically passes event args to the command (in my example an object of type SearchBoxQuerySubmittedEventArgs).

So if we define a DelegateCommand<SearchBoxQuerySubmittedEventArgs> we can access QueryText from the command.



This is not properly correct since SearchBoxQuerySubmittedEventArgs is a class defined in SearchBox control and viewmodel should not know anything about the view.

Instead, we should define a DelegateCommand<string> but how can we convert SearchBoxQuerySubmittedEventArgs to a string?



InvokeCommandAction provides InputConverter property that we can use to apply a conversion to the event args.

So we can write a custom converter to convert from SearchBoxQuerySubmittedEventArgs to string:



public class SearchBoxQuerySubmittedEventArgsToStringConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, string language)
        {
            string queryText = null;
            SearchBoxQuerySubmittedEventArgs eventArgs = value as SearchBoxQuerySubmittedEventArgs;
 
            if (eventArgs != null)
            {
                queryText = eventArgs.QueryText;
            }
 
            return queryText;
        }
 
        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            throw new NotImplementedException();
        }
    }


And then we can bind it to InputConverter property:



<SearchBox>
    <interactivity:Interaction.Behaviors>
        <behaviors:OpacityToVisibilityBehavior />
        <core:EventTriggerBehavior EventName="QuerySubmitted">
            <core:InvokeCommandAction Command="{Binding SearchCommand}" InputConverter="{StaticResource SearchBoxQuerySubmittedEventArgsToStringConverter}" />
        </core:EventTriggerBehavior>
    </interactivity:Interaction.Behaviors>
</SearchBox>


In this way we keep viewmodel separate from the view.