i am invoking the QuerySubmitted command of the AutoSuggestBox control in UWP. the command binds to ICommand in the view model. the problem is it requires to accept AutoSuggestBoxQuerySubmittedEventArgs which is pure UI and it's not acceptable in MVVM.
my code looks like that:
<AutoSuggestBox Name="SearchAutoSuggestBox"
PlaceholderText="Search by keywords"
QueryIcon="Find"
>
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="QuerySubmitted">
<core:InvokeCommandAction Command="{x:Bind ViewModel.SearchCommand}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</AutoSuggestBox>
and my view model looks like that:
public DelegateCommand<AutoSuggestBoxQuerySubmittedEventArgs> SearchCommand { get; }
public MainPageViewModel()
{
SearchCommand = new DelegateCommand<AutoSuggestBoxQuerySubmittedEventArgs>(ExecuteMethod);
}
private void ExecuteMethod(AutoSuggestBoxQuerySubmittedEventArgs o)
{
// CODE HERE
}
ofcours AutoSuggestBoxQuerySubmittedEventArgs is not acceptable in the view model. looking for alternatives... same goes to SuggestionChosen...
InvokeCommandAction has a parameter named InputConverter which you can use to convert the event args to some other parameter that can be passed to your ViewModel.
First create a IValueConverter class to extract what you need from your event args like this:-
public class AutoSuggestQueryParameterConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
// cast value to whatever EventArgs class you are expecting here
var args = (AutoSuggestBoxQuerySubmittedEventArgs)value;
// return what you need from the args
return (string)args.ChosenSuggestion;
}
}
Then use that converter in your XAML like this:
<Page.Resources>
<converters:AutoSuggestQueryParameterConverter x:Key="ArgsConverter" />
</Page.Resources>
<AutoSuggestBox Name="SearchAutoSuggestBox"
PlaceholderText="Search by keywords"
QueryIcon="Find">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="QuerySubmitted">
<core:InvokeCommandAction
Command="{x:Bind ViewModel.SearchCommand}"
InputConverter="{StaticResource ArgsConverter}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</AutoSuggestBox>
Finally in your viewmodel change your command to accept a string as parameter. So you would have the following in your vm:
public DelegateCommand<string> SearchCommand { get; }
public MainPageViewModel()
{
SearchCommand = new DelegateCommand<string>(ExecuteMethod);
}
private void ExecuteMethod(string o)
{
// CODE HERE
}
You can bind the search string (Text property) to a view model property and the events to parameter-less methods. This way the view model wont have to deal with UI objects:
XAML:
<AutoSuggestBox Header="What's your name?"
TextChanged="{x:Bind ViewModel.FilterUsuals}"
QuerySubmitted="{x:Bind ViewModel.ProcessQuery}"
SuggestionChosen="{x:Bind ViewModel.ProcessChoice}"
ItemsSource="{x:Bind ViewModel.Usuals, Mode=OneWay}"
Text="{x:Bind ViewModel.SearchText, Mode=TwoWay}"
QueryIcon="Find" />
Code behind:
public class MainPageViewModel : SomeViewModelBaseClass
{
/* Boilerplate code and constructor not included */
private string _SearchText;
public string SearchText {/* getter and setter INotyfyPropertyChange compliant */ }
private List<string> _Usuals; // Initialized on constructor
public string Usuals {/* getter and setter INotyfyPropertyChange compliant */ }
public void FilterUsuals()
{
// the search string is in SearchText Example:
Usuals = _UsualsStore.Where(u => u.Contains(_SearchText.ToLower())).ToList();
}
public void ProcessQuery() { /* TODO - search string is in SearchText */ }
public void ProcessChoice() { /* TODO - search string is in SearchText */ }
}
If you don't mind doing non pure
MVVM way.
MainPage.xaml
:
<AutoSuggestBox Name="SearchAutoSuggestBox"
PlaceholderText="Search by keywords"
QueryIcon="Find" QuerySubmitted="{x:Bind ViewModel.SearchQuerySubmitted}" IsEnabled="{x:Bind ViewModel.CanExecuteSearchCommand, Mode=TwoWay}"
>
</AutoSuggestBox>
MainPageViewModel.cs
:
public class MainPageViewModel : INotifyPropertyChanged
{
private bool _canExecuteSearchCommand;
public MainPageViewModel()
{
this.CanExecuteSearchCommand = true;
}
public bool CanExecuteSearchCommand
{
get { return _canExecuteSearchCommand; }
set
{
bool changed = _canExecuteSearchCommand != value;
_canExecuteSearchCommand = value;
if(changed)
this.OnPropertyChanged();
}
}
public void SearchQuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
{
// Just example disabling SearchBox
this.CanExecuteSearchCommand = false;
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
MainPage.cs
:
MainPageViewModel ViewModel = new MainPageViewModel();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With