UWP绑定到MVVM中的AutoSuggestBox

时间:2016-01-05 20:10:43

标签: mvvm binding uwp autosuggest

我在UWP中调用AutoSuggestBox控件的QuerySubmitted命令。 该命令在视图模型中绑定到ICommand。 问题是需要接受AutoSuggestBoxQuerySubmittedEventArgs这是纯UI,而且在MVVM中是不可接受的。

我的代码看起来像这样:

<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>

我的视图模型看起来像这样:

public DelegateCommand<AutoSuggestBoxQuerySubmittedEventArgs> SearchCommand { get; }

public MainPageViewModel()
{
    SearchCommand = new DelegateCommand<AutoSuggestBoxQuerySubmittedEventArgs>(ExecuteMethod);
}

private void ExecuteMethod(AutoSuggestBoxQuerySubmittedEventArgs o)
{
    // CODE HERE
}

ofcours AutoSuggestBoxQuerySubmittedEventArgs在视图模型中是不可接受的。 寻找替代品...... 同样适用于SuggestionChosen ......

4 个答案:

答案 0 :(得分:9)

InvokeCommandAction 有一个名为 InputConverter 的参数,您可以使用该参数将事件参数转换为可以传递给ViewModel的其他参数。

首先创建一个IValueConverter类,从你的事件args中提取你需要的东西: -

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;
       }
}

然后在XAML中使用该转换器,如下所示:

<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>

最后在viewmodel中更改命令以接受字符串作为参数。所以你的vm中会有以下内容:

public DelegateCommand<string> SearchCommand { get; }

public MainPageViewModel()
{
    SearchCommand = new DelegateCommand<string>(ExecuteMethod);
}

private void ExecuteMethod(string o)
{
    // CODE HERE
}

答案 1 :(得分:5)

您可以将搜索字符串(Text属性)绑定到视图模型属性,将事件绑定到无参数方法。这样,视图模型就不必处理UI对象:

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" />

代码背后:

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 */ }
}

答案 2 :(得分:1)

如果你不介意做non pure MVVM方式。

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();

答案 3 :(得分:0)

UWP将Command/Delegate绑定到AutoSuggestBox

中的MVVM

对于UWP移动应用程序

制作DelegateCommand类

public class DelegateCommand<T> : ICommand
{
    private readonly Action<T> executeAction;
    Func<object, bool> canExecute;

    public event EventHandler CanExecuteChanged;

    public DelegateCommand(Action<T> executeAction)
        : this(executeAction, null)
    {
        //var a = ((Page)(((Func<object, bool>)(executeAction.Target)).Target)).Name;
        //((ViewModel.VMBranchSelection)(executeAction.Target)).;

    }

    public DelegateCommand(Action<T> executeAction, Func<object, bool> canExecute)
    {
        this.executeAction = executeAction;
        this.canExecute = canExecute;
    }

    public bool CanExecute(object parameter)
    {
        return canExecute == null ? true : canExecute(parameter);
    }

    public void Execute(object parameter)
    {
        executeAction((T)parameter);
    }
    public void RaiseCanExecuteChanged()
    {
        EventHandler handler = this.CanExecuteChanged;
        if (handler != null)
        {
            handler(this, new EventArgs());
        }
    }
}

在视图模型中

    public ICommand SuggessionSelectCity_QuerySubmitted
    {
        get { return new DelegateCommand<AutoSuggestBoxQuerySubmittedEventArgs>(this.SuggessionSelectCityQuerySubmitted); }
    }

    private void     SuggessionSelectCityQuerySubmitted(AutoSuggestBoxQuerySubmittedEventArgs obj)
    {
        if (obj.ChosenSuggestion != null)
        {
            AutosuggestionTextBoxName.Text = ((ModelName)   (obj.ChosenSuggestion)).Model's Property name;
//or
AutosuggestionTextBoxName.Text =(obj.ChosenSuggestion).property name    
        }
        else
        {

        }
    }

在XAML代码中

<AutoSuggestBox Grid.Column="1" x:Name="SuggessionSelectCity"  
            PlaceholderText="Search by keywords" QueryIcon="Find"
            ItemsSource="{Binding PApplicantCityList}"

            HorizontalAlignment="Center" VerticalAlignment="Center" DisplayMemberPath="Description" Width="250" Height="45">

                <Interactivity:Interaction.Behaviors>
                    <Core:EventTriggerBehavior EventName="TextChanged">
                        <Core:EventTriggerBehavior.Actions>
                            <Core:InvokeCommandAction Command="{Binding SuggessionSelectCityTextChange}"/>
                        </Core:EventTriggerBehavior.Actions>
                    </Core:EventTriggerBehavior>

                    <Core:EventTriggerBehavior EventName="QuerySubmitted">
                        <Core:EventTriggerBehavior.Actions>
                            <Core:InvokeCommandAction Command="{Binding SuggessionSelectCity_QuerySubmitted}"/>
                        </Core:EventTriggerBehavior.Actions>
                    </Core:EventTriggerBehavior>

                    <Core:EventTriggerBehavior EventName="SuggestionChosen">
                        <Core:EventTriggerBehavior.Actions>
                            <Core:InvokeCommandAction Command="{Binding SuggessionSelectCitySuggestionChosen}"/>
                        </Core:EventTriggerBehavior.Actions>
                    </Core:EventTriggerBehavior>


                </Interactivity:Interaction.Behaviors>
            </AutoSuggestBox>
        </Grid>

在View Model for Autosuggestion TextBox Itemssource

中创建一个列表
private ObservableCollection<ResultMasterModel> ApplicantCityList;
    public ObservableCollection<ResultMasterModel> PApplicantCityList
    {
        get { return ApplicantCityList; }
        set { this.SetProperty(ref this.ApplicantCityList, value); }
    }

在上面的列表中添加一些硬代码值

在模型文件夹中创建模型

public class ResultMasterModel
{   
    public string Code { get; set; }
    public string Description { get; set; }
}